lightshortcuts 1.0.6 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -3
- package/bin/lsc.js +347 -154
- package/lib/LSC.js +3 -11
- package/lib/core/API.js +140 -8
- package/lib/core/apiUrl.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,9 +23,25 @@
|
|
|
23
23
|
**发布前需要先登录系统**,需要输入API地址和token:
|
|
24
24
|
|
|
25
25
|
```
|
|
26
|
-
lsc login
|
|
26
|
+
Usage: lsc login [options]
|
|
27
|
+
|
|
28
|
+
登录会话
|
|
29
|
+
|
|
30
|
+
Options:
|
|
31
|
+
-e, --env <type> 选择管控台的环境,e为dev、prod
|
|
32
|
+
|
|
33
|
+
示例1:
|
|
34
|
+
lsc login -e dev #切换到测试环境
|
|
35
|
+
示例2:
|
|
36
|
+
lsc login --env prod #切换到生产环境
|
|
27
37
|
```
|
|
28
38
|
|
|
39
|
+
3. 切换不同会话环境,name:dev、prod
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
lsc use <name>
|
|
43
|
+
```
|
|
44
|
+
|
|
29
45
|
3. 初始化发布配置
|
|
30
46
|
|
|
31
47
|
方式一:交互模式进行创建(推荐方式):
|
|
@@ -36,7 +52,7 @@
|
|
|
36
52
|
|
|
37
53
|
之后将在当前路径下创建发布配置文件lsc.config.json,请打开文件,根据需要做相应修改:
|
|
38
54
|
|
|
39
|
-
```
|
|
55
|
+
```
|
|
40
56
|
{
|
|
41
57
|
"pkgid": "XXXXX", //离线包唯一ID
|
|
42
58
|
"set_pkg_version": "1.0.1", //指定发布版本
|
|
@@ -78,7 +94,56 @@
|
|
|
78
94
|
|
|
79
95
|
在配置好发布文件的前提下,可以缩写成以下命令:
|
|
80
96
|
|
|
81
|
-
```
|
|
97
|
+
```
|
|
82
98
|
lsc login && lsc publish
|
|
83
99
|
```
|
|
100
|
+
6. 会话注销
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
Usage: lsc logout [options]
|
|
104
|
+
|
|
105
|
+
注销会话
|
|
106
|
+
|
|
107
|
+
Options:
|
|
108
|
+
-e, --env <type> 选择管控台的环境
|
|
109
|
+
-l, --link <link> 注销指定管控台链接
|
|
110
|
+
-t, --token <token> 注销指定token
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
7. 帮助
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
➜ ~ lsc --help
|
|
117
|
+
Usage: lsc [options] [command]
|
|
118
|
+
|
|
119
|
+
Options:
|
|
120
|
+
-V, --version output the version number
|
|
121
|
+
-h, --help display help for command
|
|
122
|
+
|
|
123
|
+
Commands:
|
|
124
|
+
login [options] 登录会话
|
|
125
|
+
logout [options] 注销会话
|
|
126
|
+
use <name> 设置当前发布版本
|
|
127
|
+
config 交互式配置离线包发布参数
|
|
128
|
+
init 快速初始化配置模板
|
|
129
|
+
publish|p 发布离线包
|
|
130
|
+
batch|b 发布离线包
|
|
131
|
+
deal <version> 处理离线包兼容版本相互重叠的情况,谨慎使用!
|
|
132
|
+
clean <all> 批量处理离线包兼容版本相互重叠的情况,谨慎使用!
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
8. 清理指定离线包兼容版本范围:`lsc deal version`
|
|
136
|
+
|
|
137
|
+
9. 批量清理指定离线包兼容版本范围(需管理员权限):`lsc clean all`
|
|
138
|
+
|
|
139
|
+
附:
|
|
140
|
+
|
|
141
|
+
1、在Windows系统运行命令时,如果提示“此系统上禁止运行脚本”,则按如下方法解决:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
方法:
|
|
145
|
+
1、以管理员身份运行 Windows PowerShell(管理员)
|
|
146
|
+
2、输入 set-ExecutionPolicy RemoteSigned ,然后输入A 回车
|
|
147
|
+
3、还可以通过 get-ExecutionPolicy 查看当前的状态
|
|
148
|
+
```
|
|
84
149
|
|
package/bin/lsc.js
CHANGED
|
@@ -14,21 +14,37 @@ const lscrcPath = path.join(
|
|
|
14
14
|
process.env.HOME || process.env.USERPROFILE,
|
|
15
15
|
".lscrc.json"
|
|
16
16
|
);
|
|
17
|
+
|
|
17
18
|
const defaultConfig = require("../lib/defaults");
|
|
18
|
-
const {
|
|
19
|
+
const {
|
|
20
|
+
checkSession,
|
|
21
|
+
initAxiosConfig,
|
|
22
|
+
logout,
|
|
23
|
+
dealVersionList,
|
|
24
|
+
batchDealVersionList
|
|
25
|
+
} = require("../lib/core/API");
|
|
19
26
|
// 主目录下登录配置文件
|
|
20
27
|
let confPath = path.join(process.cwd(), "./lsc.config.json");
|
|
21
28
|
|
|
22
|
-
program.version("0.0.
|
|
29
|
+
program.version("0.0.8");
|
|
23
30
|
|
|
24
31
|
// 登录并保存token
|
|
25
32
|
let lightBaseURL = "";
|
|
26
33
|
let loginQuestions = [
|
|
34
|
+
{
|
|
35
|
+
type: "list",
|
|
36
|
+
message: "现在配置的环境是?",
|
|
37
|
+
name: "env",
|
|
38
|
+
choices: [
|
|
39
|
+
{ key: 0, value: "dev", name: "测试环境", checked: true },
|
|
40
|
+
{ key: 1, value: "prod", name: "生产环境" },
|
|
41
|
+
],
|
|
42
|
+
},
|
|
27
43
|
{
|
|
28
44
|
type: "input",
|
|
29
45
|
message: "请输入API前缀地址:",
|
|
30
46
|
name: "lightBaseURL",
|
|
31
|
-
default: ()=>lightBaseURL || defaultConfig.lightBaseURL,
|
|
47
|
+
default: () => lightBaseURL || defaultConfig.lightBaseURL,
|
|
32
48
|
validate: async (url) => {
|
|
33
49
|
lightBaseURL = url;
|
|
34
50
|
return true;
|
|
@@ -45,7 +61,7 @@ let loginQuestions = [
|
|
|
45
61
|
},
|
|
46
62
|
];
|
|
47
63
|
//校验是否已经登录
|
|
48
|
-
const loginAction = async function () {
|
|
64
|
+
const loginAction = async function (env) {
|
|
49
65
|
fileExists(lscrcPath)
|
|
50
66
|
.then(async (res) => {
|
|
51
67
|
// 是否需要交互处理
|
|
@@ -53,16 +69,29 @@ const loginAction = async function () {
|
|
|
53
69
|
if (res) {
|
|
54
70
|
// 存在文件
|
|
55
71
|
let lscRc = require(lscrcPath);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
if (
|
|
73
|
+
lscRc[`${env}`] &&
|
|
74
|
+
lscRc[`${env}`].lightBaseURL &&
|
|
75
|
+
lscRc[`${env}`].token
|
|
76
|
+
) {
|
|
77
|
+
lightBaseURL = lscRc[`${env}`].lightBaseURL;
|
|
78
|
+
// console.log(lightBaseURL);
|
|
79
|
+
let res = await validSession(
|
|
80
|
+
lscRc[`${env}`].lightBaseURL,
|
|
81
|
+
lscRc[`${env}`].token
|
|
82
|
+
);
|
|
83
|
+
if (!res) {
|
|
84
|
+
// 已有API链接
|
|
85
|
+
// loginQuestions.shift();
|
|
86
|
+
console.log(lscRc[`${env}`]);
|
|
87
|
+
console.log("\n");
|
|
88
|
+
} else {
|
|
89
|
+
// token仍有效
|
|
90
|
+
console.log(`已登录,当前通道:${env}`);
|
|
91
|
+
needLoginProcessF = false;
|
|
92
|
+
}
|
|
62
93
|
} else {
|
|
63
|
-
|
|
64
|
-
console.log("已登录");
|
|
65
|
-
needLoginProcessF = false;
|
|
94
|
+
needLoginProcessF = true;
|
|
66
95
|
}
|
|
67
96
|
} else {
|
|
68
97
|
// 不存在文件
|
|
@@ -70,8 +99,22 @@ const loginAction = async function () {
|
|
|
70
99
|
}
|
|
71
100
|
if (needLoginProcessF) {
|
|
72
101
|
inquirer.prompt(loginQuestions).then(async (answers) => {
|
|
73
|
-
|
|
74
|
-
|
|
102
|
+
// let lscRc = require(lscrcPath);
|
|
103
|
+
// lscRc.currentEnv = env;
|
|
104
|
+
let { lightBaseURL, token, env } = answers;
|
|
105
|
+
// await writeConfig(answers, lscrcPath);
|
|
106
|
+
|
|
107
|
+
let lscRc = {};
|
|
108
|
+
let fef = await fileExists(lscrcPath);
|
|
109
|
+
|
|
110
|
+
if (fef) {
|
|
111
|
+
lscRc = require(lscrcPath);
|
|
112
|
+
}
|
|
113
|
+
lscRc.currentEnv = env;
|
|
114
|
+
lscRc[`${env}`] = { lightBaseURL, token };
|
|
115
|
+
|
|
116
|
+
await writeConfig(lscRc, lscrcPath);
|
|
117
|
+
// console.log(JSON.stringify(lscRc));
|
|
75
118
|
return true;
|
|
76
119
|
});
|
|
77
120
|
}
|
|
@@ -83,146 +126,223 @@ const loginAction = async function () {
|
|
|
83
126
|
};
|
|
84
127
|
program
|
|
85
128
|
.command("login")
|
|
86
|
-
.description("
|
|
87
|
-
.
|
|
88
|
-
|
|
129
|
+
.description("登录会话")
|
|
130
|
+
.option("-e, --env <type>", "选择管控台的环境")
|
|
131
|
+
.action(async (opts) => {
|
|
132
|
+
let { env } = opts;
|
|
133
|
+
if (env == undefined) {
|
|
134
|
+
// 没传环境变量参数
|
|
135
|
+
let fef = await fileExists(lscrcPath);
|
|
136
|
+
if (fef) {
|
|
137
|
+
let { currentEnv } = require(lscrcPath);
|
|
138
|
+
if (currentEnv) {
|
|
139
|
+
env = currentEnv;
|
|
140
|
+
} else {
|
|
141
|
+
env = "dev";
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
env = "dev";
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
await loginAction(env);
|
|
89
148
|
});
|
|
90
149
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
{
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
150
|
+
// 注销会话
|
|
151
|
+
program
|
|
152
|
+
.command("logout")
|
|
153
|
+
.description("注销会话")
|
|
154
|
+
.option("-e, --env <type>", "选择管控台的环境")
|
|
155
|
+
.option("-l, --link <link>", "注销指定管控台链接")
|
|
156
|
+
.option("-t, --token <token>", "注销指定token")
|
|
157
|
+
.action(async (opts) => {
|
|
158
|
+
let { env, link, token } = opts;
|
|
159
|
+
let baseUrl, authToken;
|
|
160
|
+
if (env == undefined) {
|
|
161
|
+
// 没传env环境变量参数
|
|
162
|
+
let fef = await fileExists(lscrcPath);
|
|
163
|
+
if (fef) {
|
|
164
|
+
// 有本地会话配置,读取本地会话
|
|
165
|
+
let r = require(lscrcPath);
|
|
166
|
+
if (r.currentEnv) {
|
|
167
|
+
// 有本地会话
|
|
168
|
+
env = r.currentEnv;
|
|
169
|
+
//如果传入url,token则用传入的,否则用本地的;
|
|
170
|
+
baseUrl = link ? link : r[`${env}`].lightBaseURL;
|
|
171
|
+
authToken = token ? token : r[`${env}`].token;
|
|
172
|
+
} else {
|
|
173
|
+
console.log("不存在本地会话,请传入url,token");
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
// 不存在本地会话时
|
|
177
|
+
console.log("不存在本地会话,请传入url,token");
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (baseUrl && authToken) {
|
|
181
|
+
await initAxiosConfig(baseUrl, authToken);
|
|
182
|
+
let f = await logout(token);
|
|
183
|
+
console.log(`注销${f ? "成功" : "失败"}`);
|
|
184
|
+
} else {
|
|
185
|
+
console.log("不存在本地会话,请传入url,token");
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// 设置当前发布版本
|
|
190
|
+
program
|
|
191
|
+
.command("use <name>")
|
|
192
|
+
.description("设置当前发布版本")
|
|
193
|
+
.action(async (opts) => {
|
|
194
|
+
let fef = await fileExists(lscrcPath);
|
|
195
|
+
if (fef) {
|
|
196
|
+
let lscRc = require(lscrcPath);
|
|
197
|
+
lscRc.currentEnv = opts;
|
|
198
|
+
if (lscRc[`${opts}`]) {
|
|
199
|
+
await writeConfig(lscRc, lscrcPath);
|
|
200
|
+
} else {
|
|
201
|
+
console.log("不存在的离线包环境,请先进行登录:lsc login");
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
console.log("登录文件不存在,请先进行登录:lsc login");
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
program
|
|
209
|
+
.command("config")
|
|
210
|
+
.description("交互式配置离线包发布参数")
|
|
211
|
+
.action(function () {
|
|
212
|
+
let initConfig = {},
|
|
213
|
+
initAnswers = {};
|
|
214
|
+
inquirer
|
|
215
|
+
.prompt([
|
|
216
|
+
// {
|
|
217
|
+
// type: "input",
|
|
218
|
+
// message: "请输入token:",
|
|
219
|
+
// name: "token",
|
|
220
|
+
// },
|
|
221
|
+
{
|
|
222
|
+
type: "input",
|
|
223
|
+
message: "请输入离线包id:",
|
|
224
|
+
name: "pkgid",
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
type: "input",
|
|
228
|
+
message: "请指定离线包发布版本号:",
|
|
229
|
+
name: "set_pkg_version",
|
|
230
|
+
default: "1.0.1",
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
type: "input",
|
|
234
|
+
message: "APP版本iOS版本范围:",
|
|
235
|
+
name: "ios_version_scope",
|
|
236
|
+
default: "7.0.6",
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
type: "input",
|
|
240
|
+
message: "APP版本Android版本范围:",
|
|
241
|
+
name: "android_version_scope",
|
|
242
|
+
default: "7.0.6.0",
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
type: "checkbox",
|
|
246
|
+
message: "请选择发布的APP:",
|
|
247
|
+
name: "publish_app_arr",
|
|
248
|
+
choices: [
|
|
249
|
+
{
|
|
250
|
+
key: "3577",
|
|
251
|
+
value: "3592",
|
|
252
|
+
name: "开发版_iOS",
|
|
253
|
+
checked: true,
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
key: "3577",
|
|
257
|
+
value: "3577",
|
|
258
|
+
name: "开发版_安卓",
|
|
259
|
+
checked: true,
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
validate(answer) {
|
|
263
|
+
if (answer.length < 1) {
|
|
264
|
+
return "请至少选择一项";
|
|
265
|
+
}
|
|
266
|
+
return true;
|
|
134
267
|
},
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
type: "input",
|
|
271
|
+
message: "离线包压缩包存放相对位置:",
|
|
272
|
+
name: "pkg_dir",
|
|
273
|
+
default: "./dist/",
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
type: "input",
|
|
277
|
+
message: "离线包名称:",
|
|
278
|
+
name: "pkg_zip_name",
|
|
279
|
+
default: "dist.zip",
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
type: "list",
|
|
283
|
+
message: "是否处理上一版本离线包?",
|
|
284
|
+
name: "task_status",
|
|
285
|
+
choices: [
|
|
286
|
+
{ key: 0, value: 0, name: "保留", checked: true },
|
|
287
|
+
{ key: 1, value: 1, name: "暂停" },
|
|
288
|
+
{ key: 2, value: 2, name: "结束" },
|
|
289
|
+
],
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
type: "input",
|
|
293
|
+
message: "发布日志:",
|
|
294
|
+
name: "release_desc",
|
|
295
|
+
default: "功能更新",
|
|
296
|
+
when: (answers) => {
|
|
297
|
+
initAnswers = Object.assign({}, answers);
|
|
298
|
+
// console.log("initAnswers",initAnswers);
|
|
299
|
+
return true;
|
|
140
300
|
},
|
|
141
|
-
],
|
|
142
|
-
validate(answer) {
|
|
143
|
-
if (answer.length < 1) {
|
|
144
|
-
return "请至少选择一项";
|
|
145
|
-
}
|
|
146
|
-
return true;
|
|
147
301
|
},
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
name: "task_status",
|
|
165
|
-
choices: [
|
|
166
|
-
{ key: 0, value: 0, name: "保留", checked: true },
|
|
167
|
-
{ key: 1, value: 1, name: "暂停" },
|
|
168
|
-
{ key: 2, value: 2, name: "结束" },
|
|
169
|
-
],
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
type: "input",
|
|
173
|
-
message: "发布日志:",
|
|
174
|
-
name: "release_desc",
|
|
175
|
-
default: "功能更新",
|
|
176
|
-
when: (answers) => {
|
|
177
|
-
initAnswers = Object.assign({}, answers);
|
|
178
|
-
// console.log("initAnswers",initAnswers);
|
|
179
|
-
return true;
|
|
302
|
+
// {
|
|
303
|
+
// type: "input",
|
|
304
|
+
// message: "请输入API前缀地址:",
|
|
305
|
+
// name: "lightBaseURL",
|
|
306
|
+
// default: "https://xxx.xxx.xxx/lightadmin/pas-api",
|
|
307
|
+
// when: (answers) => {
|
|
308
|
+
// initAnswers = Object.assign({}, answers);
|
|
309
|
+
// // console.log("initAnswers",initAnswers);
|
|
310
|
+
// return true;
|
|
311
|
+
// },
|
|
312
|
+
// },
|
|
313
|
+
{
|
|
314
|
+
type: "confirm",
|
|
315
|
+
message: "是否使用以上配置?",
|
|
316
|
+
name: "useConfig",
|
|
317
|
+
default: true,
|
|
180
318
|
},
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
// // console.log("initAnswers",initAnswers);
|
|
190
|
-
// return true;
|
|
191
|
-
// },
|
|
192
|
-
// },
|
|
193
|
-
{
|
|
194
|
-
type: "confirm",
|
|
195
|
-
message: "是否使用以上配置?",
|
|
196
|
-
name: "useConfig",
|
|
197
|
-
default: true,
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
type: "confirm",
|
|
201
|
-
message: "是否保存配置?",
|
|
202
|
-
name: "saveConfig",
|
|
203
|
-
default: true,
|
|
204
|
-
when: function (answers) {
|
|
205
|
-
return answers.useConfig;
|
|
319
|
+
{
|
|
320
|
+
type: "confirm",
|
|
321
|
+
message: "是否保存配置?",
|
|
322
|
+
name: "saveConfig",
|
|
323
|
+
default: true,
|
|
324
|
+
when: function (answers) {
|
|
325
|
+
return answers.useConfig;
|
|
326
|
+
},
|
|
206
327
|
},
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
328
|
+
])
|
|
329
|
+
.then((asw) => {
|
|
330
|
+
let { useConfig, saveConfig } = asw;
|
|
331
|
+
if (useConfig) {
|
|
332
|
+
let totalConfig = {
|
|
333
|
+
...initAnswers,
|
|
334
|
+
apps_name: defaultConfig.publishInfo.apps_name,
|
|
335
|
+
};
|
|
336
|
+
if (saveConfig) {
|
|
337
|
+
// 保存配置
|
|
338
|
+
writeConfig(totalConfig);
|
|
339
|
+
}
|
|
340
|
+
console.log(totalConfig);
|
|
341
|
+
} else {
|
|
342
|
+
console.log("已结束!");
|
|
219
343
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
console.log("已结束!");
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
});
|
|
344
|
+
});
|
|
345
|
+
});
|
|
226
346
|
|
|
227
347
|
// 初始化配置模板
|
|
228
348
|
const initConfAction = function () {
|
|
@@ -255,9 +375,12 @@ const initConfAction = function () {
|
|
|
255
375
|
}
|
|
256
376
|
});
|
|
257
377
|
};
|
|
258
|
-
program
|
|
259
|
-
|
|
260
|
-
|
|
378
|
+
program
|
|
379
|
+
.command("init")
|
|
380
|
+
.description("快速初始化配置模板")
|
|
381
|
+
.action(function () {
|
|
382
|
+
initConfAction();
|
|
383
|
+
});
|
|
261
384
|
|
|
262
385
|
// 单项目发布
|
|
263
386
|
program
|
|
@@ -269,7 +392,9 @@ program
|
|
|
269
392
|
feConF = await fileExists(confPath);
|
|
270
393
|
//是否存在配置文件
|
|
271
394
|
if (feLscF && feConF) {
|
|
272
|
-
const
|
|
395
|
+
const lscRC = require(lscrcPath),
|
|
396
|
+
{ currentEnv } = lscRC,
|
|
397
|
+
{ lightBaseURL, token } = lscRC[`${currentEnv}`];
|
|
273
398
|
const publishConfArgs = require(confPath);
|
|
274
399
|
|
|
275
400
|
if (publishConfArgs.publishInfo) {
|
|
@@ -309,9 +434,12 @@ program
|
|
|
309
434
|
// 批量离线包发布.已经包名作为pkgid
|
|
310
435
|
program
|
|
311
436
|
.command("batch")
|
|
437
|
+
.description("发布离线包")
|
|
312
438
|
.alias("b")
|
|
313
439
|
.action(async function () {
|
|
314
|
-
const
|
|
440
|
+
const lscRC = require(lscrcPath),
|
|
441
|
+
{ currentEnv } = lscRC,
|
|
442
|
+
{ lightBaseURL, token } = lscRC[`${currentEnv}`];
|
|
315
443
|
const publishConfArgs = require(confPath);
|
|
316
444
|
|
|
317
445
|
let currPath = path.join(process.cwd(), publishConfArgs.pkg_dir);
|
|
@@ -332,13 +460,78 @@ program
|
|
|
332
460
|
}
|
|
333
461
|
});
|
|
334
462
|
|
|
463
|
+
// 处理离线包兼容版本相互重叠的情况
|
|
464
|
+
program
|
|
465
|
+
.command("deal version")
|
|
466
|
+
.description("处理离线包兼容版本相互重叠的情况,谨慎使用!")
|
|
467
|
+
.action(async function () {
|
|
468
|
+
let dv = [
|
|
469
|
+
{
|
|
470
|
+
type: "input",
|
|
471
|
+
message: "请输入app_id:",
|
|
472
|
+
name: "app_id",
|
|
473
|
+
default:3592
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
type: "input",
|
|
477
|
+
message: "请输入pkg_id:",
|
|
478
|
+
name: "pkg_id",
|
|
479
|
+
default:2307
|
|
480
|
+
},
|
|
481
|
+
];
|
|
482
|
+
inquirer.prompt(dv).then(async function (aws) {
|
|
483
|
+
const {app_id, pkg_id} = aws;
|
|
484
|
+
let f = await fileExists(lscrcPath);
|
|
485
|
+
if (f) {
|
|
486
|
+
let lscRc = require(lscrcPath),
|
|
487
|
+
{ currentEnv } = lscRc;
|
|
488
|
+
const { lightBaseURL, token } = lscRc[`${currentEnv}`];
|
|
489
|
+
await initAxiosConfig(lightBaseURL, token);
|
|
490
|
+
await dealVersionList({app_id, pkg_id});
|
|
491
|
+
} else {
|
|
492
|
+
console.log("登录文件不存在,请先进行登录:lsc login");
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
// 处理离线包兼容版本相互重叠的情况
|
|
498
|
+
program
|
|
499
|
+
.command("clean all")
|
|
500
|
+
.description("批量处理离线包兼容版本相互重叠的情况,谨慎使用!")
|
|
501
|
+
.action(async function () {
|
|
502
|
+
console.log("批量处理离线包兼容版本相互重叠的情况,谨慎使用!")
|
|
503
|
+
let dv = [
|
|
504
|
+
{
|
|
505
|
+
type: "input",
|
|
506
|
+
message: "请输入app_id列表,以逗号分隔:",
|
|
507
|
+
name: "app_id",
|
|
508
|
+
default:"3592,3577,3580,3562"
|
|
509
|
+
}
|
|
510
|
+
];
|
|
511
|
+
inquirer.prompt(dv).then(async function (aws) {
|
|
512
|
+
const {app_id} = aws;
|
|
513
|
+
console.log((app_id+'').split(','));
|
|
514
|
+
let ids = (app_id+'').split(',');
|
|
515
|
+
let f = await fileExists(lscrcPath);
|
|
516
|
+
if (f) {
|
|
517
|
+
let lscRc = require(lscrcPath),
|
|
518
|
+
{ currentEnv } = lscRc;
|
|
519
|
+
const { lightBaseURL, token } = lscRc[`${currentEnv}`];
|
|
520
|
+
await initAxiosConfig(lightBaseURL, token);
|
|
521
|
+
await batchDealVersionList(ids);
|
|
522
|
+
} else {
|
|
523
|
+
console.log("登录文件不存在,请先进行登录:lsc login");
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
|
|
335
528
|
async function writeConfig(configArgs, path = "./lsc.config.json") {
|
|
336
529
|
// 写入文件内容(如果文件不存在会创建一个文件)
|
|
337
530
|
writeFile(path, JSON.stringify(configArgs), { flag: "w" }, function (err) {
|
|
338
531
|
if (err) {
|
|
339
532
|
throw err;
|
|
340
533
|
}
|
|
341
|
-
console.log("
|
|
534
|
+
console.log("已更新");
|
|
342
535
|
});
|
|
343
536
|
}
|
|
344
537
|
|
|
@@ -347,7 +540,7 @@ async function validSession(lightBaseURL, token) {
|
|
|
347
540
|
await initAxiosConfig(lightBaseURL, token);
|
|
348
541
|
let f = await checkSession(token);
|
|
349
542
|
if (!f) {
|
|
350
|
-
await console.log("\n会话已过期或者无效,请重新确认:", f);
|
|
543
|
+
await console.log("\n会话已过期或者无效,请重新确认:", f, "\n");
|
|
351
544
|
}
|
|
352
545
|
return f;
|
|
353
546
|
}
|
package/lib/LSC.js
CHANGED
|
@@ -29,6 +29,7 @@ const {
|
|
|
29
29
|
queryOfflinePkgList,
|
|
30
30
|
queryOfflineVersionlist,
|
|
31
31
|
syncPkgList,
|
|
32
|
+
dealVersionList
|
|
32
33
|
} = require("./core/API");
|
|
33
34
|
|
|
34
35
|
//在APP上发布指定离线包主逻辑
|
|
@@ -82,19 +83,10 @@ async function publish(h5pkgid, app_id) {
|
|
|
82
83
|
}),
|
|
83
84
|
e = qotRes.filter((val) => val.status == 0),
|
|
84
85
|
f = e[0];
|
|
85
|
-
//
|
|
86
|
+
// 处理上一版本的问题:保持、暂停、下架
|
|
86
87
|
if (task_status != 0) {
|
|
87
88
|
let sm = { 0: "发布", 1: "暂停", 2: "下架" };
|
|
88
|
-
|
|
89
|
-
id: f.id,
|
|
90
|
-
status: task_status, //0发布,1暂停,2下架
|
|
91
|
-
app_id,
|
|
92
|
-
});
|
|
93
|
-
console.log(
|
|
94
|
-
`版本${prevVerInfo.version}${sm[task_status]}${
|
|
95
|
-
uotRes ? "成功" : "失败"
|
|
96
|
-
}`
|
|
97
|
-
);
|
|
89
|
+
await dealVersionList({ app_id, pkg_id, status: task_status });
|
|
98
90
|
}
|
|
99
91
|
}
|
|
100
92
|
}
|
package/lib/core/API.js
CHANGED
|
@@ -9,16 +9,31 @@ const { ApiList } = require("./apiUrl");
|
|
|
9
9
|
// 存储APP的离线包
|
|
10
10
|
let allOfflinePkgLists = {};
|
|
11
11
|
|
|
12
|
-
const initAxiosConfig = async function(lightBaseURL,token){
|
|
12
|
+
const initAxiosConfig = async function (lightBaseURL, token) {
|
|
13
13
|
//全局配置
|
|
14
14
|
axios.defaults.baseURL = lightBaseURL;
|
|
15
15
|
axios.defaults.headers["cookie"] = `token=${token}`;
|
|
16
|
+
axios.defaults.headers["User-Agent"] = "LightShortcuts Pro";
|
|
16
17
|
};
|
|
17
18
|
|
|
19
|
+
// 添加请求拦截器
|
|
20
|
+
axios.interceptors.request.use(
|
|
21
|
+
function (config) {
|
|
22
|
+
// 在发送请求之前做些什么
|
|
23
|
+
// console.log(config)
|
|
24
|
+
return config;
|
|
25
|
+
},
|
|
26
|
+
function (error) {
|
|
27
|
+
// 对请求错误做些什么
|
|
28
|
+
return Promise.reject(error);
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
|
|
18
32
|
// 添加响应拦截器
|
|
19
33
|
axios.interceptors.response.use(
|
|
20
34
|
function (response) {
|
|
21
35
|
// 2xx 范围内的状态码都会触发该函数。
|
|
36
|
+
// console.log(response.data);
|
|
22
37
|
return response;
|
|
23
38
|
},
|
|
24
39
|
function (error) {
|
|
@@ -29,8 +44,7 @@ axios.interceptors.response.use(
|
|
|
29
44
|
|
|
30
45
|
//校验会话有效性
|
|
31
46
|
const checkSession = async function (token) {
|
|
32
|
-
if(token){
|
|
33
|
-
|
|
47
|
+
if (token) {
|
|
34
48
|
}
|
|
35
49
|
return new Promise((resolve, reject) => {
|
|
36
50
|
axios
|
|
@@ -50,6 +64,28 @@ const checkSession = async function (token) {
|
|
|
50
64
|
});
|
|
51
65
|
};
|
|
52
66
|
|
|
67
|
+
// 注销会话
|
|
68
|
+
const logout = async function (token) {
|
|
69
|
+
return new Promise((resolve, reject) => {
|
|
70
|
+
axios
|
|
71
|
+
.get(ApiList.logout)
|
|
72
|
+
.then((res) => {
|
|
73
|
+
let { data } = res;
|
|
74
|
+
if (data.err_no === 0) {
|
|
75
|
+
resolve(true);
|
|
76
|
+
} else {
|
|
77
|
+
resolve(false);
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
.catch((err) => {
|
|
81
|
+
console.warn(
|
|
82
|
+
`注销会话报错,原因是:${err.response.data.data[0].error_info}`
|
|
83
|
+
);
|
|
84
|
+
resolve(false);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
53
89
|
// 上传文件,__filePath:绝对路径
|
|
54
90
|
const fileUpload = async function (__filePath) {
|
|
55
91
|
return new Promise((resolve, reject) => {
|
|
@@ -160,7 +196,7 @@ const queryOfflineVersionlist = async function (app_id, h5app_id) {
|
|
|
160
196
|
{ id } = t;
|
|
161
197
|
//pkg_id
|
|
162
198
|
let qovRes = await axios.get(
|
|
163
|
-
`${ApiList.queryOfflineVersionlist}?app_id=${app_id}&pkg_id=${id}&page_no=1&page_size=
|
|
199
|
+
`${ApiList.queryOfflineVersionlist}?app_id=${app_id}&pkg_id=${id}&page_no=1&page_size=30`
|
|
164
200
|
);
|
|
165
201
|
return qovRes.data;
|
|
166
202
|
};
|
|
@@ -173,7 +209,9 @@ const addOfflineH5pkg = async function (app_id, h5app_id, name) {
|
|
|
173
209
|
),
|
|
174
210
|
copFlag = copRes.data.data;
|
|
175
211
|
let conRes = await axios.get(
|
|
176
|
-
`${ApiList.checkOfflinePkgname}?app_id=${app_id}&name=${encodeURI(
|
|
212
|
+
`${ApiList.checkOfflinePkgname}?app_id=${app_id}&name=${encodeURI(
|
|
213
|
+
name
|
|
214
|
+
)}`
|
|
177
215
|
),
|
|
178
216
|
conFlag = conRes.data.data;
|
|
179
217
|
if (copFlag || conFlag) {
|
|
@@ -264,7 +302,6 @@ const queryOfflineTask = async function (args) {
|
|
|
264
302
|
)}&page_no=1&page_size=5`
|
|
265
303
|
)
|
|
266
304
|
.then(function (res) {
|
|
267
|
-
// console.log("获取指定版本下的发布任务列表:", JSON.stringify(res.data));
|
|
268
305
|
const { err_no, data } = res.data;
|
|
269
306
|
if (err_no == 0) {
|
|
270
307
|
resolve(data.list);
|
|
@@ -289,7 +326,6 @@ const updateOfflineTask = async function (uotArgs = {}) {
|
|
|
289
326
|
data: qs.stringify(uotArgs),
|
|
290
327
|
})
|
|
291
328
|
.then(function (res) {
|
|
292
|
-
console.log("更新发布任务状态:", res.data);
|
|
293
329
|
const { err_no } = res.data;
|
|
294
330
|
if (err_no == 0) {
|
|
295
331
|
resolve(true);
|
|
@@ -304,8 +340,102 @@ const updateOfflineTask = async function (uotArgs = {}) {
|
|
|
304
340
|
});
|
|
305
341
|
};
|
|
306
342
|
|
|
343
|
+
// 处理版本范围相互覆盖的离线包
|
|
344
|
+
const dealVersionList = async function ({ app_id, pkg_id, status = 2, name }) {
|
|
345
|
+
if (pkg_id == null) {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
let qovRes = await axios.get(
|
|
349
|
+
`${ApiList.queryOfflineVersionlist}?app_id=${app_id}&pkg_id=${pkg_id}&page_no=1&page_size=30`
|
|
350
|
+
);
|
|
351
|
+
let { list } = qovRes.data.data;
|
|
352
|
+
let versionList = [];
|
|
353
|
+
// 获取要下架的版本号ID;
|
|
354
|
+
let toDoId = list.reduce((acc, cur) => {
|
|
355
|
+
let {
|
|
356
|
+
id,
|
|
357
|
+
ios_version_scope,
|
|
358
|
+
android_version_scope,
|
|
359
|
+
status,
|
|
360
|
+
version,
|
|
361
|
+
release_type,
|
|
362
|
+
} = cur;
|
|
363
|
+
// if (ios_version_scope == "") {
|
|
364
|
+
// console.warn(`ios_version_scope == ""`, cur);
|
|
365
|
+
// }
|
|
366
|
+
if (status == 1 && release_type == 0) {
|
|
367
|
+
if (versionList.includes(ios_version_scope)) {
|
|
368
|
+
let o = acc[`${ios_version_scope}`];
|
|
369
|
+
acc[`${ios_version_scope}`] = [...o, { id, version }];
|
|
370
|
+
} else {
|
|
371
|
+
acc[`${ios_version_scope}`] = [];
|
|
372
|
+
versionList.push(ios_version_scope);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return acc;
|
|
377
|
+
}, {});
|
|
378
|
+
|
|
379
|
+
for (const key in toDoId) {
|
|
380
|
+
if (Object.hasOwnProperty.call(toDoId, key)) {
|
|
381
|
+
const vl = toDoId[key];
|
|
382
|
+
if (vl.length > 0) {
|
|
383
|
+
for (let index = 0; index < vl.length; index++) {
|
|
384
|
+
const val = vl[index];
|
|
385
|
+
try {
|
|
386
|
+
let t = await todoVersion(app_id, val.id);
|
|
387
|
+
let sm = { 0: "发布", 1: "暂停", 2: "下架" },tips=sm[`${status}`];
|
|
388
|
+
console.log(
|
|
389
|
+
`${app_id}${name ? name : ""}版本范围:${key},版本号:${
|
|
390
|
+
val.version
|
|
391
|
+
},版本ID:${val.id},处理情况:${tips}${t ? "成功" : "失败"}`
|
|
392
|
+
);
|
|
393
|
+
} catch (error) {}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
async function todoVersion(app_id, version_id) {
|
|
400
|
+
const qot = await queryOfflineTask({ app_id, version_id });
|
|
401
|
+
// console.log("qot",qot)
|
|
402
|
+
// return;
|
|
403
|
+
let tmp = qot.reduce((acc, cur) => {
|
|
404
|
+
if (cur.status == 0) {
|
|
405
|
+
acc = [...acc, cur.id];
|
|
406
|
+
}
|
|
407
|
+
return acc;
|
|
408
|
+
}, []);
|
|
409
|
+
let taskId = tmp[0];
|
|
410
|
+
// 下架
|
|
411
|
+
return await updateOfflineTask({
|
|
412
|
+
id: taskId,
|
|
413
|
+
status: 2,
|
|
414
|
+
app_id,
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
// 批处理版本范围相互覆盖的离线包
|
|
420
|
+
const batchDealVersionList = async function (ids, h5app_id, status = 2) {
|
|
421
|
+
const pkgLists = await queryOfflinePkgList(ids);
|
|
422
|
+
for (const key in pkgLists) {
|
|
423
|
+
if (Object.hasOwnProperty.call(pkgLists, key)) {
|
|
424
|
+
const ele = pkgLists[key];
|
|
425
|
+
for (let index = 0; index < ele.length; index++) {
|
|
426
|
+
const f = ele[index];
|
|
427
|
+
let { app_id, pkg_id, name } = f;
|
|
428
|
+
if (pkg_id != null) {
|
|
429
|
+
await dealVersionList({ app_id, pkg_id, status: 2, name });
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
|
|
307
436
|
module.exports = {
|
|
308
437
|
allOfflinePkgLists,
|
|
438
|
+
logout,
|
|
309
439
|
checkSession,
|
|
310
440
|
fileUpload,
|
|
311
441
|
queryOfflinePkgList,
|
|
@@ -317,5 +447,7 @@ module.exports = {
|
|
|
317
447
|
queryOfflineTask,
|
|
318
448
|
updateOfflineTask,
|
|
319
449
|
syncPkgList,
|
|
320
|
-
initAxiosConfig
|
|
450
|
+
initAxiosConfig,
|
|
451
|
+
dealVersionList,
|
|
452
|
+
batchDealVersionList,
|
|
321
453
|
};
|
package/lib/core/apiUrl.js
CHANGED
|
@@ -5,6 +5,7 @@ const offlineURlPrefix = `/light/light-platform-client/v/appdiy/offline/`;
|
|
|
5
5
|
const ApiList = {
|
|
6
6
|
fileUpload: "/ltcommon/file/v/upload?bizType=h5_offline_src",
|
|
7
7
|
checkSession: "/light/light-platform-client/v/auth/check_session",
|
|
8
|
+
logout:"/light/light-platform-client/v/auth/logout",
|
|
8
9
|
queryOfflinePkgList: offlineURlPrefix + "query_offline_pkglist1",
|
|
9
10
|
queryOfflineVersionlist: offlineURlPrefix + "query_offline_versionlist",
|
|
10
11
|
addOfflineH5pkg: offlineURlPrefix + "add_offline_h5pkg",
|