lightshortcuts 1.0.0 → 1.0.4

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 CHANGED
@@ -1,48 +1,68 @@
1
1
  # Light快捷指令
2
2
 
3
- 仅适用于Light管控台的快捷指令,用于快速处理离线包的一些处理,如发布等。请向相关平台管理员获取地址和token。
3
+ 仅适用于Light管控台的快捷指令,用于快速处理离线包的一些处理,如发布等。请向相关平台管理员获取API地址和token、AppID
4
4
 
5
5
  #### 使用说明
6
6
 
7
7
  1. 安装
8
8
 
9
- ```bash
9
+ 使用npm或yarn进行全局安装,Linux系统需要管理员权限:
10
+
11
+ ```
10
12
  npm install -g lightshortcuts
11
13
  ```
12
14
 
13
- 2. 初始化发布配置
15
+ 升级包:
16
+
17
+ ```shell
18
+ npm update -g lightshortcuts
19
+ ```
20
+
21
+ 2. 登录管控台系统
22
+
23
+ **发布前需要先登录系统**,需要输入API地址和token:
24
+
25
+ ```
26
+ lsc login
27
+ ```
28
+
29
+ 3. 初始化发布配置
30
+
31
+ 方式一:交互模式进行创建(推荐方式):
14
32
 
15
33
  ```bash
16
- lsc init
34
+ lsc config
17
35
  ```
18
36
 
19
37
  之后将在当前路径下创建发布配置文件lsc.config.json,请打开文件,根据需要做相应修改:
20
38
 
21
39
  ```json
22
40
  {
23
- "publishInfo": {
24
- "token": "XXXXX", //登录token
25
- "pkgid": "XXXXX", //离线包ID
26
- "set_pkg_version": "1.0.1", //指定发布版本
27
- "publish_app_arr": [3577, 3592], //发布到指定APP,默认开发版
28
- "apps_name": {
29
- "3592": "开发版_iOS",
30
- "3577": "开发版_安卓"
31
- },
32
- "android_version_scope": "7.0.6.0", //Android端离线包兼容版本
33
- "ios_version_scope": "7.0.6", //iOS端离线包兼容版本
34
- "pkg_zip_name": "dist.zip",//离线包压缩包文件名
35
- "pkg_dir": "./dist/", //离线包相对所在路径
36
- "release_desc": "功能更新", //发布日志
37
- "task_status": "0" //发布当前版本后,对上一版本的处理:0:发布(不处理),1:暂停,2:结束(下架)
38
- },
39
- "lightBaseURL": "https://xxx.xxx.xxx/lightadmin/pas-api"//Light管控台地址
41
+ "pkgid": "XXXXX", //离线包唯一ID
42
+ "set_pkg_version": "1.0.1", //指定发布版本
43
+ "publish_app_arr": [3577, 3592], //AppID列表发布到指定App,默认开发版
44
+ "apps_name": {
45
+ "3592": "开发版_iOS",
46
+ "3577": "开发版_安卓"
47
+ },
48
+ "android_version_scope": "7.0.6.0", //Android端离线包兼容版本
49
+ "ios_version_scope": "7.0.6", //iOS端离线包兼容版本
50
+ "pkg_zip_name": "dist.zip",//离线包压缩包文件名
51
+ "pkg_dir": "./dist/", //离线包相对所在路径
52
+ "release_desc": "若干功能更新", //发布日志
53
+ "task_status": "0" //发布当前版本后,对上一版本的处理:0:发布(不处理),1:暂停,2:结束(下架)
40
54
  }
41
55
  ```
42
56
 
43
-
57
+ 方式二:使用模板一键初始化:
58
+
59
+ ```bash
60
+ lsc init
61
+ ```
62
+
63
+ 之后再根据项目进行修改。
44
64
 
45
- 3. 离线包发布
65
+ 4. 离线包发布
46
66
 
47
67
  - 单项目发布:
48
68
 
@@ -56,4 +76,9 @@
56
76
  lsc batch #或简写为 lsc b
57
77
  ```
58
78
 
59
-
79
+ 在配置好发布文件的前提下,可以缩写成以下命令:
80
+
81
+ ```bash
82
+ lsc login && lsc publish
83
+ ```
84
+
package/bin/lsc.js CHANGED
@@ -1,56 +1,136 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { access, statSync, constants, writeFile, readdirSync } = require("fs");
3
+ const { writeFile } = require("fs");
4
4
  const path = require("path");
5
5
  const { Command } = require("commander");
6
6
  const inquirer = require("inquirer");
7
7
  const program = new Command();
8
8
  const { LSC } = require("../index");
9
9
  const { merge, getZipFileList } = require("../lib/utils");
10
- const loadModSync = require("../lib/helpers/loadModSync");
10
+ const fileExists = require("../lib/helpers/file-exists");
11
11
 
12
12
  // 读取发布配置文件
13
+ const lscrcPath = path.join(process.env.HOME, ".lscrc.json");
13
14
  const defaultConfig = require("../lib/defaults");
14
- const { checkSession } = require("../lib/core/API");
15
- const { config } = require("process");
15
+ const { checkSession, initAxiosConfig } = require("../lib/core/API");
16
+ // 主目录下登录配置文件
16
17
  let confPath = path.join(process.cwd(), "./lsc.config.json");
17
18
 
18
- program.version("0.0.1");
19
+ program.version("0.0.3");
20
+
21
+ // 登录并保存token
22
+ let lightBaseURL = "";
23
+ let loginQuestions = [
24
+ {
25
+ type: "input",
26
+ message: "请输入API前缀地址:",
27
+ name: "lightBaseURL",
28
+ default: lightBaseURL || defaultConfig.lightBaseURL,
29
+ validate: async (url) => {
30
+ lightBaseURL = url;
31
+ return true;
32
+ },
33
+ },
34
+ {
35
+ type: "input",
36
+ message: "请输入token:",
37
+ name: "token",
38
+ validate: async (token) => {
39
+ return await validSession(lightBaseURL, token);
40
+ },
41
+ validatingText: "正在校验token的有效性...",
42
+ },
43
+ ];
44
+ //校验是否已经登录
45
+ const loginAction = async function () {
46
+ fileExists(lscrcPath)
47
+ .then(async (res) => {
48
+ // 是否需要交互处理
49
+ let needLoginProcessF = true;
50
+ if (res) {
51
+ // 存在文件
52
+ let lscRc = require(lscrcPath);
53
+ lightBaseURL = lscRc.lightBaseURL;
54
+ let res = await validSession(lscRc.lightBaseURL, lscRc.token);
55
+ if (!res) {
56
+ // 已有API链接
57
+ // loginQuestions.shift();
58
+ } else {
59
+ // token仍有效
60
+ console.log("已登录");
61
+ needLoginProcessF = false;
62
+ }
63
+ } else {
64
+ // 不存在文件
65
+ needLoginProcessF = true;
66
+ }
67
+ if (needLoginProcessF) {
68
+ inquirer.prompt(loginQuestions).then(async (answers) => {
69
+ await writeConfig(answers, lscrcPath);
70
+ console.log(JSON.stringify(answers));
71
+ return true;
72
+ });
73
+ }
74
+ })
75
+ .catch((err) => {
76
+ console.log(err);
77
+ return false;
78
+ });
79
+ };
80
+ program
81
+ .command("login")
82
+ .description("输入登录token")
83
+ .action(async () => {
84
+ await loginAction();
85
+ });
19
86
 
20
87
  program.command("config").action(function () {
88
+ let initConfig = {},
89
+ initAnswers = {};
21
90
  inquirer
22
91
  .prompt([
92
+ // {
93
+ // type: "input",
94
+ // message: "请输入token:",
95
+ // name: "token",
96
+ // },
23
97
  {
24
98
  type: "input",
25
- message: "请输入token:",
26
- name: "token",
99
+ message: "请输入离线包id:",
100
+ name: "pkgid",
27
101
  },
28
102
  {
29
103
  type: "input",
30
- message: "请输入离线包id:",
31
- name: "h5pkgid",
104
+ message: "请指定离线包发布版本号:",
105
+ name: "set_pkg_version",
106
+ default: "1.0.1",
32
107
  },
33
108
  {
34
109
  type: "input",
35
- message: "请输入离线包名称:",
36
- name: "name",
110
+ message: "APP版本iOS版本范围:",
111
+ name: "ios_version_scope",
112
+ default: "7.0.6",
37
113
  },
38
114
  {
39
115
  type: "input",
40
- message: "请指定发布版本号:",
41
- name: "version",
42
- default: "1.0.1",
116
+ message: "APP版本Android版本范围:",
117
+ name: "android_version_scope",
118
+ default: "7.0.6.0",
43
119
  },
44
120
  {
45
121
  type: "checkbox",
46
122
  message: "请选择发布的APP:",
47
- name: "apps",
123
+ name: "publish_app_arr",
48
124
  choices: [
49
125
  {
126
+ key: "3577",
127
+ value: "3592",
50
128
  name: "开发版_iOS",
51
129
  checked: true,
52
130
  },
53
131
  {
132
+ key: "3577",
133
+ value: "3577",
54
134
  name: "开发版_安卓",
55
135
  checked: true,
56
136
  },
@@ -64,7 +144,7 @@ program.command("config").action(function () {
64
144
  },
65
145
  {
66
146
  type: "input",
67
- message: "离线包压缩包存放位置:",
147
+ message: "离线包压缩包存放相对位置:",
68
148
  name: "pkg_dir",
69
149
  default: "./dist/",
70
150
  },
@@ -78,55 +158,101 @@ program.command("config").action(function () {
78
158
  type: "rawlist",
79
159
  message: "是否处理上一版本离线包?",
80
160
  name: "task_status",
81
- default: "保留",
82
- choices: ["保留", "暂停", "下架"],
161
+ choices: [
162
+ { key: 0, value: 0, name: "保留", checked: true },
163
+ { key: 1, value: 1, name: "暂停" },
164
+ { key: 2, value: 2, name: "结束" },
165
+ ],
166
+ },
167
+ {
168
+ type: "input",
169
+ message: "发布日志:",
170
+ name: "release_desc",
171
+ default: "功能更新",
172
+ when: (answers) => {
173
+ initAnswers = Object.assign({}, answers);
174
+ // console.log("initAnswers",initAnswers);
175
+ return true;
176
+ },
177
+ },
178
+ // {
179
+ // type: "input",
180
+ // message: "请输入API前缀地址:",
181
+ // name: "lightBaseURL",
182
+ // default: "https://xxx.xxx.xxx/lightadmin/pas-api",
183
+ // when: (answers) => {
184
+ // initAnswers = Object.assign({}, answers);
185
+ // // console.log("initAnswers",initAnswers);
186
+ // return true;
187
+ // },
188
+ // },
189
+ {
190
+ type: "confirm",
191
+ message: "是否使用以上配置?",
192
+ name: "useConfig",
193
+ default: true,
194
+ },
195
+ {
196
+ type: "confirm",
197
+ message: "是否保存配置?",
198
+ name: "saveConfig",
199
+ default: true,
200
+ when: function (answers) {
201
+ return answers.useConfig;
202
+ },
83
203
  },
84
204
  ])
85
- .then((answer) => {
86
- // 用户输入的结果最终会在这里输出
87
- console.log(answer);
205
+ .then((asw) => {
206
+ let { useConfig, saveConfig } = asw;
207
+ if (useConfig) {
208
+ let totalConfig = {
209
+ ...initAnswers,
210
+ apps_name: defaultConfig.publishInfo.apps_name,
211
+ };
212
+ if (saveConfig) {
213
+ // 保存配置
214
+ writeConfig(totalConfig);
215
+ }
216
+ console.log(totalConfig);
217
+ } else {
218
+ console.log("已结束!");
219
+ }
88
220
  });
89
221
  });
90
222
 
91
- program.command("init").action(function () {
92
- let confPath = path.join(process.cwd(), "./lsc.config.json");
93
- access(confPath, constants.F_OK, (err) => {
94
- if (!err) {
223
+ // 初始化配置模板
224
+ const initConfAction = function () {
225
+ fileExists(confPath).then((res) => {
226
+ if (res) {
227
+ console.log("注意,配置文件已经存在!!!内容如下:");
228
+ console.log(require(confPath));
95
229
  // 存在配置文件,唤起交互输入
96
230
  inquirer
97
231
  .prompt([
98
232
  {
99
233
  type: "confirm",
100
- message: "注意!!!配置文件已经存在,是否重新初始化?",
234
+ message: "是否重新初始化?",
101
235
  name: "initConfig",
102
236
  default: false,
103
237
  },
104
238
  ])
105
239
  .then((answer) => {
106
240
  if (answer.initConfig) {
107
- writeConfig();
241
+ let mergeConf = Object.assign(
242
+ defaultConfig.publishInfo
243
+ );
244
+ writeConfig(mergeConf, confPath);
108
245
  } else {
109
246
  console.log("配置无变化");
110
247
  }
111
248
  });
112
249
  } else {
113
- writeConfig();
250
+ writeConfig(defaultConfig);
114
251
  }
115
- var writeConfig = function () {
116
- // 写入文件内容(如果文件不存在会创建一个文件)
117
- writeFile(
118
- "./lsc.config.json",
119
- JSON.stringify(defaultConfig),
120
- { flag: "w" },
121
- function (err) {
122
- if (err) {
123
- throw err;
124
- }
125
- console.log("创建配置模板成功,请打开文件进行相应修改");
126
- }
127
- );
128
- };
129
252
  });
253
+ };
254
+ program.command("init").action(function () {
255
+ initConfAction();
130
256
  });
131
257
 
132
258
  // 单项目发布
@@ -134,23 +260,46 @@ program
134
260
  .command("publish")
135
261
  .alias("p")
136
262
  .description("发布离线包")
137
- .action(() => {
138
- access(confPath, constants.F_OK, (err) => {
139
- if (!err) {
140
- try {
141
- let lscConfig = require(confPath);
142
- let totalConfig = merge(defaultConfig, lscConfig);
143
- LSC(totalConfig);
144
- } catch (error) {
145
- console.log("主程序异常", error);
146
- }
147
- } else {
148
- // 不存在配置文件,唤起交互输入
263
+ .action(async () => {
264
+ let feLscF = await fileExists(lscrcPath),
265
+ feConF = await fileExists(confPath);
266
+ //是否存在配置文件
267
+ if (feLscF && feConF) {
268
+ const { lightBaseURL, token } = require(lscrcPath);
269
+ const publishConfArgs = require(confPath);
270
+
271
+ if (publishConfArgs.publishInfo) {
149
272
  console.log(
150
- "不存在配置文件,请先进行配置或者使用如下命令创建:lsc init"
273
+ "温馨提示:程序已升级!\n请使用命令lsc config 或 lsc init 重新生成发布配置"
151
274
  );
275
+ return;
152
276
  }
153
- });
277
+
278
+ try {
279
+ // let lscConfig = require(confPath);
280
+ let totalConfig = {
281
+ publishInfo: { ...publishConfArgs, token },
282
+ lightBaseURL,
283
+ };
284
+ // console.log("发布配置:\n", totalConfig);
285
+ LSC(totalConfig);
286
+ } catch (error) {
287
+ console.log("主程序异常", error);
288
+ }
289
+ } else {
290
+ // 不存在配置文件,唤起交互输入
291
+ let t = "",
292
+ f = "";
293
+ if (!feLscF) {
294
+ f = "登录";
295
+ t = "lsc login";
296
+ }
297
+ if (!feConF) {
298
+ f = "离线包发布";
299
+ t = "lsc config 或 lsc init";
300
+ }
301
+ console.log(`不存在${f}配置文件,请使用命令创建:${t}`);
302
+ }
154
303
  });
155
304
 
156
305
  // 批量离线包发布.已经包名作为pkgid
@@ -158,20 +307,45 @@ program
158
307
  .command("batch")
159
308
  .alias("b")
160
309
  .action(async function () {
161
- let currPath = path.join(process.cwd(), "./dist/");
310
+ const { lightBaseURL, token } = require(lscrcPath);
311
+ const publishConfArgs = require(confPath);
312
+
313
+ let currPath = path.join(process.cwd(), publishConfArgs.pkg_dir);
162
314
  let zipLists = await getZipFileList(currPath);
163
315
  for (let i = 0; i < zipLists.length; i++) {
164
316
  const e = zipLists[i],
165
317
  s = e.split("."),
166
318
  pkgid = s[0];
167
- let lscConfig = require(confPath);
168
- let totalConfig = merge(defaultConfig, lscConfig);
319
+ let totalConfig = {
320
+ publishInfo: { ...publishConfArgs, token },
321
+ lightBaseURL,
322
+ };
169
323
  let batchConfig = merge(totalConfig, {
170
324
  publishInfo: { pkgid, pkg_zip_name: e },
171
325
  });
172
- // console.log("batchConfig", batchConfig);
326
+ // console.log("batchConfig\n", batchConfig);
173
327
  await LSC(batchConfig);
174
328
  }
175
329
  });
176
330
 
331
+ async function writeConfig(configArgs, path = "./lsc.config.json") {
332
+ // 写入文件内容(如果文件不存在会创建一个文件)
333
+ writeFile(path, JSON.stringify(configArgs), { flag: "w" }, function (err) {
334
+ if (err) {
335
+ throw err;
336
+ }
337
+ console.log("创建配置模板成功,可根据需要进行相应修改");
338
+ });
339
+ }
340
+
341
+ // 查询会话的有效性
342
+ async function validSession(lightBaseURL, token) {
343
+ await initAxiosConfig(lightBaseURL, token);
344
+ let f = await checkSession(token);
345
+ if (!f) {
346
+ await console.log("\n会话已过期或者无效,请重新确认:", f);
347
+ }
348
+ return f;
349
+ }
350
+
177
351
  program.parse(process.argv);
package/lib/core/API.js CHANGED
@@ -9,6 +9,12 @@ const { ApiList } = require("./apiUrl");
9
9
  // 存储APP的离线包
10
10
  let allOfflinePkgLists = {};
11
11
 
12
+ const initAxiosConfig = async function(lightBaseURL,token){
13
+ //全局配置
14
+ axios.defaults.baseURL = lightBaseURL;
15
+ axios.defaults.headers["cookie"] = `token=${token}`;
16
+ };
17
+
12
18
  // 添加响应拦截器
13
19
  axios.interceptors.response.use(
14
20
  function (response) {
@@ -311,4 +317,5 @@ module.exports = {
311
317
  queryOfflineTask,
312
318
  updateOfflineTask,
313
319
  syncPkgList,
320
+ initAxiosConfig
314
321
  };
package/lib/defaults.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var defaults = {
3
3
  publishInfo: {
4
- token: "XXXXX", //登录token
4
+ // token: "XXXXX", //登录token
5
5
  pkgid: "XXXXX", //离线包ID
6
6
  set_pkg_version: "1.0.1", //指定发布版本
7
7
  publish_app_arr: [3577, 3592], //发布到指定APP,默认开发版
@@ -0,0 +1,10 @@
1
+ const fs = require('fs')
2
+ const util = require('util')
3
+
4
+ const stat = util.promisify(fs.stat)
5
+
6
+ const fileExists = async (file) => stat(file)
7
+ .then((stat) => stat.isFile())
8
+ .catch(() => false)
9
+
10
+ module.exports = fileExists
package/lsc.config.json CHANGED
@@ -1,14 +1,11 @@
1
1
  {
2
- "publishInfo": {
3
- "token": "xxx.xxx.xxx",
4
- "pkgid": "xxx.xxx.xxx",
5
- "set_pkg_version": "1.2.9",
6
- "publish_app_arr": [3592, 3577],
7
- "android_version_scope": "7.0.7.0",
8
- "ios_version_scope": "7.0.7",
9
- "pkg_zip_name": "xxx.xxx.xxx.zip",
10
- "pkg_dir": "./dist/",
11
- "task_status": "2"
12
- },
13
- "lightBaseURL": "https://xxx.xxx.xxx/lightadmin/pas-api"
2
+ "token": "XXXXX",
3
+ "pkgid": "XXXXX",
4
+ "set_pkg_version": "1.2.1",
5
+ "publish_app_arr": [3592, 3577],
6
+ "android_version_scope": "7.0.7.0",
7
+ "ios_version_scope": "7.0.7",
8
+ "pkg_zip_name": "XXXXX.zip",
9
+ "pkg_dir": "./dist/",
10
+ "task_status": "2"
14
11
  }
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "inquirer": "^8.2.0",
10
10
  "qs": "^6.10.3"
11
11
  },
12
- "version": "1.0.0",
12
+ "version": "1.0.4",
13
13
  "description": "Light离线包自动发布工具",
14
14
  "main": "index.js",
15
15
  "devDependencies": {},