@whyour/qinglong 0.15.6 → 0.17.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.
Files changed (51) hide show
  1. package/.env.example +1 -0
  2. package/docker/310.Dockerfile +6 -1
  3. package/docker/Dockerfile +2 -1
  4. package/docker/docker-entrypoint.sh +1 -0
  5. package/docker/front.conf +16 -0
  6. package/other.config.js +13 -0
  7. package/package.json +3 -3
  8. package/sample/config.sample.sh +19 -8
  9. package/sample/notify.js +49 -32
  10. package/sample/notify.py +286 -145
  11. package/shell/check.sh +1 -0
  12. package/shell/share.sh +13 -1
  13. package/shell/update.sh +34 -22
  14. package/static/build/api/dependence.js +12 -0
  15. package/static/build/config/index.js +1 -0
  16. package/static/build/config/util.js +26 -23
  17. package/static/build/data/dependence.js +1 -0
  18. package/static/build/loaders/server.js +0 -21
  19. package/static/build/loaders/update.js +79 -0
  20. package/static/build/services/dependence.js +35 -4
  21. package/static/build/services/notify.js +4 -13
  22. package/static/build/services/system.js +17 -32
  23. package/static/build/shared/pLimit.js +18 -5
  24. package/static/build/update.js +29 -0
  25. package/static/dist/{419.f9258e2f.async.js → 419.71c3c9c2.async.js} +1 -1
  26. package/static/dist/{833.c59c5023.async.js → 833.ea0fd669.async.js} +1 -1
  27. package/static/dist/8430.0291dda0.async.js +1 -0
  28. package/static/dist/index.html +1 -1
  29. package/static/dist/{layouts__index.817c948a.async.js → layouts__index.a51b2768.async.js} +1 -1
  30. package/static/dist/{src__pages__crontab__detail.7d1c2d15.async.js → src__pages__crontab__detail.2ab4f3e8.async.js} +1 -1
  31. package/static/dist/{src__pages__crontab__index.5aece157.async.js → src__pages__crontab__index.719429ac.async.js} +1 -1
  32. package/static/dist/src__pages__dependence__index.52fca7ba.async.js +1 -0
  33. package/static/dist/src__pages__dependence__logModal.baba01d6.async.js +1 -0
  34. package/static/dist/src__pages__dependence__type.860703e8.async.js +1 -0
  35. package/static/dist/{src__pages__log__index.757b3471.async.js → src__pages__log__index.44c6a008.async.js} +1 -1
  36. package/static/dist/{src__pages__script__index.ed44bc1b.async.js → src__pages__script__index.2a8d8477.async.js} +1 -1
  37. package/static/dist/src__pages__setting__checkUpdate.43e62d05.async.js +1 -0
  38. package/static/dist/src__pages__setting__dependence.28193e94.async.js +1 -0
  39. package/static/dist/src__pages__setting__index.7ab054fb.async.js +1 -0
  40. package/static/dist/src__pages__setting__other.2c4534ef.async.js +1 -0
  41. package/static/dist/src__pages__setting__progress.7d65aebf.async.js +1 -0
  42. package/static/dist/{umi.889d3656.js → umi.3bb00f35.js} +1 -1
  43. package/version.yaml +8 -12
  44. package/static/dist/8008.89ba3d06.async.js +0 -1
  45. package/static/dist/src__pages__dependence__index.27d29203.async.js +0 -1
  46. package/static/dist/src__pages__dependence__logModal.b44459a9.async.js +0 -1
  47. package/static/dist/src__pages__setting__checkUpdate.42020a45.async.js +0 -1
  48. package/static/dist/src__pages__setting__dependence.2efb8ee3.async.js +0 -1
  49. package/static/dist/src__pages__setting__index.3e2ad723.async.js +0 -1
  50. package/static/dist/src__pages__setting__other.a029d99a.async.js +0 -1
  51. package/static/dist/src__pages__setting__progress.65e2e878.async.js +0 -1
package/shell/check.sh CHANGED
@@ -81,6 +81,7 @@ main() {
81
81
  check_ql
82
82
  check_nginx
83
83
  check_pm2
84
+ reload_update
84
85
  reload_pm2
85
86
  echo -e "\n=====> 检测结束\n"
86
87
  }
package/shell/share.sh CHANGED
@@ -298,7 +298,7 @@ git_clone_scripts() {
298
298
 
299
299
  set_proxy "$proxy"
300
300
 
301
- git clone --depth=1 $part_cmd $url $dir
301
+ git clone -q --depth=1 $part_cmd $url $dir
302
302
  exit_status=$?
303
303
 
304
304
  unset_proxy
@@ -310,6 +310,11 @@ random_range() {
310
310
  echo $((RANDOM % ($end - $beg) + $beg))
311
311
  }
312
312
 
313
+ delete_pm2() {
314
+ cd $dir_root
315
+ pm2 delete ecosystem.config.js
316
+ }
317
+
313
318
  reload_pm2() {
314
319
  cd $dir_root
315
320
  restore_env_vars
@@ -317,6 +322,13 @@ reload_pm2() {
317
322
  pm2 startOrGracefulReload ecosystem.config.js
318
323
  }
319
324
 
325
+ reload_update() {
326
+ cd $dir_root
327
+ restore_env_vars
328
+ pm2 flush &>/dev/null
329
+ pm2 startOrGracefulReload other.config.js
330
+ }
331
+
320
332
  diff_time() {
321
333
  local format="$1"
322
334
  local begin_time="$2"
package/shell/update.sh CHANGED
@@ -34,7 +34,6 @@ output_list_add_drop() {
34
34
  if [[ -s $list ]]; then
35
35
  echo -e "检测到有${type}的定时任务:"
36
36
  cat $list
37
- echo
38
37
  fi
39
38
  }
40
39
 
@@ -45,7 +44,7 @@ del_cron() {
45
44
  local path=$2
46
45
  local detail=""
47
46
  local ids=""
48
- echo -e "开始尝试自动删除失效的定时任务..."
47
+ echo -e "\n开始尝试自动删除失效的定时任务..."
49
48
  for cron in $(cat $list_drop); do
50
49
  local id=$(cat $list_crontab_user | grep -E "$cmd_task.* $cron" | perl -pe "s|.*ID=(.*) $cmd_task.* $cron\.*|\1|" | head -1 | awk -F " " '{print $1}')
51
50
  if [[ $ids ]]; then
@@ -76,7 +75,7 @@ del_cron() {
76
75
  add_cron() {
77
76
  local list_add=$1
78
77
  local path=$2
79
- echo -e "开始尝试自动添加定时任务..."
78
+ echo -e "\n开始尝试自动添加定时任务..."
80
79
  local detail=""
81
80
  cd $dir_scripts
82
81
  for file in $(cat $list_add); do
@@ -86,19 +85,20 @@ add_cron() {
86
85
  cron_line=$(
87
86
  perl -ne "{
88
87
  print if /.*([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*]( |,|\").*$file_name/
89
- }" $file |
88
+ }" $file 2>/dev/null |
90
89
  perl -pe "{
91
90
  s|[^\d\*]*(([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*])( \|,\|\").*/?$file_name.*|\1|g;
92
91
  s|\*([\d\*])(.*)|\1\2|g;
93
92
  s| | |g;
94
- }" | sort -u | head -1
93
+ }" 2>/dev/null | sort -u | head -1
95
94
  )
96
- cron_name=$(grep "new Env" $file | awk -F "\(" '{print $2}' | awk -F "\)" '{print $1}' | sed 's:.*\('\''\|"\)\([^"'\'']*\)\('\''\|"\).*:\2:' | sed 's:"::g' | sed "s:'::g" | head -1)
97
- [[ -z $cron_name ]] && cron_name="$file_name"
98
95
  [[ -z $cron_line ]] && cron_line=$(grep "cron:" $file | awk -F ":" '{print $2}' | head -1 | xargs)
99
96
  [[ -z $cron_line ]] && cron_line=$(grep "cron " $file | awk -F "cron \"" '{print $2}' | awk -F "\" " '{print $1}' | head -1 | xargs)
100
97
  [[ -z $cron_line ]] && cron_line="$default_cron"
101
- result=$(add_cron_api "$cron_line:$cmd_task $file:$cron_name:$SUB_ID")
98
+ cron_name=$(grep "new Env" $file | awk -F "\(" '{print $2}' | awk -F "\)" '{print $1}' | sed 's:.*\('\''\|"\)\([^"'\'']*\)\('\''\|"\).*:\2:' | sed 's:"::g' | sed "s:'::g" | head -1)
99
+ [[ -z $cron_name ]] && cron_name=$(grep "name:" $file | awk -F ":" '{print $2}' | head -1 | xargs)
100
+ [[ -z $cron_name ]] && cron_name=$(basename "$file_name")
101
+ result=$(add_cron_api "${cron_line}:${cmd_task} ${file}:${cron_name}:${SUB_ID}")
102
102
  echo -e "$result"
103
103
  if [[ $detail ]]; then
104
104
  detail="${detail}${result}\n"
@@ -135,10 +135,10 @@ update_repo() {
135
135
  git_clone_scripts "${formatUrl}" ${repo_path} "${branch}" "${proxy}"
136
136
 
137
137
  if [[ $exit_status -eq 0 ]]; then
138
- echo -e "\n拉取 ${uniq_path} 成功...\n"
138
+ echo -e "拉取 ${uniq_path} 成功...\n"
139
139
  diff_scripts "$repo_path" "$author" "$path" "$blackword" "$dependence" "$extensions" "$autoAddCron" "$autoDelCron"
140
140
  else
141
- echo -e "\n拉取 ${uniq_path} 失败,请检查日志...\n"
141
+ echo -e "拉取 ${uniq_path} 失败,请检查日志...\n"
142
142
  fi
143
143
  }
144
144
 
@@ -195,7 +195,7 @@ update_raw() {
195
195
  [[ -z $cron_line ]] && cron_line=$(grep "cron:" $raw_file_name | awk -F ":" '{print $2}' | head -1 | xargs)
196
196
  [[ -z $cron_line ]] && cron_line=$(grep "cron " $raw_file_name | awk -F "cron \"" '{print $2}' | awk -F "\" " '{print $1}' | head -1 | xargs)
197
197
  [[ -z $cron_line ]] && cron_line="$default_cron"
198
- result=$(add_cron_api "$cron_line:$cmd_task $filename:$cron_name:$SUB_ID")
198
+ result=$(add_cron_api "${cron_line}:${cmd_task} ${filename}:${cron_name}:${SUB_ID}")
199
199
  echo -e "$result\n"
200
200
  notify_api "新增任务通知" "\n$result"
201
201
  # update_cron_api "$cron_line:$cmd_task $filename:$cron_name:$cron_id"
@@ -231,22 +231,25 @@ usage() {
231
231
  }
232
232
 
233
233
  reload_qinglong() {
234
+ delete_pm2
235
+
234
236
  local reload_target="${1}"
235
237
  local primary_branch="master"
236
- if [[ "${QL_BRANCH}" == "develop" ]]; then
237
- primary_branch="develop"
238
+ if [[ "${QL_BRANCH}" == "develop" ]] || [[ "${QL_BRANCH}" == "debian" ]] || [[ "${QL_BRANCH}" == "debian-dev" ]]; then
239
+ primary_branch="${QL_BRANCH}"
238
240
  fi
239
241
 
240
242
  if [[ "$reload_target" == 'system' ]]; then
241
- cp -rf ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/
243
+ rm -rf ${dir_root}/back ${dir_root}/cli ${dir_root}/docker ${dir_root}/sample ${dir_root}/shell ${dir_root}/src
244
+ mv -f ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/
242
245
  rm -rf $dir_static/*
243
- cp -rf ${dir_tmp}/qinglong-static-${primary_branch}/* ${dir_static}/
246
+ mv -f ${dir_tmp}/qinglong-static-${primary_branch}/* ${dir_static}/
244
247
  cp -f $file_config_sample $dir_config/config.sample.sh
245
248
  fi
246
249
 
247
250
  if [[ "$reload_target" == 'data' ]]; then
248
- rm -rf ${dir_root}/data
249
- cp -rf ${dir_tmp}/data ${dir_root}/
251
+ rm -rf ${dir_root}/data/*
252
+ mv -f ${dir_tmp}/data/* ${dir_root}/data/
250
253
  fi
251
254
 
252
255
  reload_pm2
@@ -258,7 +261,7 @@ update_qinglong() {
258
261
  local mirror="gitee"
259
262
  local downloadQLUrl="https://gitee.com/whyour/qinglong/repository/archive"
260
263
  local downloadStaticUrl="https://gitee.com/whyour/qinglong-static/repository/archive"
261
- local githubStatus=$(curl -s -m 2 -IL "https://google.com" | grep 200)
264
+ local githubStatus=$(curl -s --noproxy "*" -m 2 -IL "https://google.com" | grep 200)
262
265
  if [[ ! -z $githubStatus ]]; then
263
266
  mirror="github"
264
267
  downloadQLUrl="https://github.com/whyour/qinglong/archive/refs/heads"
@@ -310,9 +313,12 @@ check_update_dep() {
310
313
  echo -e "更新包下载成功..."
311
314
 
312
315
  if [[ "$needRestart" == 'true' ]]; then
313
- cp -rf ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/
316
+ delete_pm2
317
+
318
+ rm -rf ${dir_root}/back ${dir_root}/cli ${dir_root}/docker ${dir_root}/sample ${dir_root}/shell ${dir_root}/src
319
+ mv -f ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/
314
320
  rm -rf $dir_static/*
315
- cp -rf ${dir_tmp}/qinglong-static-${primary_branch}/* ${dir_static}/
321
+ mv -f ${dir_tmp}/qinglong-static-${primary_branch}/* ${dir_static}/
316
322
  cp -f $file_config_sample $dir_config/config.sample.sh
317
323
 
318
324
  reload_pm2
@@ -417,9 +423,15 @@ gen_list_repo() {
417
423
  fi
418
424
 
419
425
  for file in ${files}; do
426
+ dirPath=$(dirname "$file")
420
427
  filename=$(basename "$file")
421
- cp -f $file "$dir_scripts/${uniq_path}/${filename}"
422
- echo "${uniq_path}/${filename}" >>"$dir_list_tmp/${uniq_path}_scripts.list"
428
+ filePath="${uniq_path}/${filename}"
429
+ if [[ $dirPath ]] && [[ $dirPath != '.' ]]; then
430
+ mkdir -p "${dir_scripts}/${uniq_path}/${dirPath}"
431
+ filePath="${uniq_path}/${dirPath}/${filename}"
432
+ fi
433
+ cp -f $file "${dir_scripts}/$filePath"
434
+ echo "$filePath" >>"$dir_list_tmp/${uniq_path}_scripts.list"
423
435
  # cron_id=$(cat $list_crontab_user | grep -E "$cmd_task.* ${uniq_path}_${filename}" | perl -pe "s|.*ID=(.*) $cmd_task.* ${uniq_path}_${filename}\.*|\1|" | head -1 | awk -F " " '{print $1}')
424
436
  # if [[ $cron_id ]]; then
425
437
  # result=$(update_cron_command_api "$cmd_task ${uniq_path}/${filename}:$cron_id")
@@ -111,5 +111,17 @@ exports.default = (app) => {
111
111
  return next(e);
112
112
  }
113
113
  });
114
+ route.put('/cancel', (0, celebrate_1.celebrate)({
115
+ body: celebrate_1.Joi.array().items(celebrate_1.Joi.number().required()),
116
+ }), async (req, res, next) => {
117
+ try {
118
+ const dependenceService = typedi_1.Container.get(dependence_1.default);
119
+ await dependenceService.cancel(req.body);
120
+ return res.send({ code: 200 });
121
+ }
122
+ catch (e) {
123
+ return next(e);
124
+ }
125
+ });
114
126
  };
115
127
  //# sourceMappingURL=dependence.js.map
@@ -56,6 +56,7 @@ exports.default = {
56
56
  port: parseInt(process.env.BACK_PORT, 10),
57
57
  cronPort: parseInt(process.env.CRON_PORT, 10),
58
58
  publicPort: parseInt(process.env.PUBLIC_PORT, 10),
59
+ updatePort: parseInt(process.env.UPDATE_PORT, 10),
59
60
  secret: process.env.SECRET || (0, share_1.createRandomString)(16, 32),
60
61
  logs: {
61
62
  level: process.env.LOG_LEVEL || 'silly',
@@ -352,30 +352,33 @@ function parseHeaders(headers) {
352
352
  return parsed;
353
353
  }
354
354
  exports.parseHeaders = parseHeaders;
355
- function parseBody(body, contentType) {
355
+ function parseString(input, valueFormatFn) {
356
+ const regex = /(\w+):\s*((?:(?!\n\w+:).)*)/g;
357
+ const matches = {};
358
+ let match;
359
+ while ((match = regex.exec(input)) !== null) {
360
+ const [, key, value] = match;
361
+ const _key = key.trim();
362
+ if (!_key || matches[_key]) {
363
+ continue;
364
+ }
365
+ let _value = value.trim();
366
+ try {
367
+ _value = valueFormatFn ? valueFormatFn(_value) : _value;
368
+ const jsonValue = JSON.parse(_value);
369
+ matches[_key] = jsonValue;
370
+ }
371
+ catch (error) {
372
+ matches[_key] = _value;
373
+ }
374
+ }
375
+ return matches;
376
+ }
377
+ function parseBody(body, contentType, valueFormatFn) {
356
378
  if (contentType === 'text/plain' || !body) {
357
379
  return body;
358
380
  }
359
- const parsed = {};
360
- let key;
361
- let val;
362
- let i;
363
- body &&
364
- body.split('\n').forEach(function parser(line) {
365
- i = line.indexOf(':');
366
- key = line.substring(0, i).trim();
367
- val = line.substring(i + 1).trim();
368
- if (!key || parsed[key]) {
369
- return;
370
- }
371
- try {
372
- const jsonValue = JSON.parse(val);
373
- parsed[key] = jsonValue;
374
- }
375
- catch (error) {
376
- parsed[key] = val;
377
- }
378
- });
381
+ const parsed = parseString(body, valueFormatFn);
379
382
  switch (contentType) {
380
383
  case 'multipart/form-data':
381
384
  return Object.keys(parsed).reduce((p, c) => {
@@ -416,8 +419,8 @@ async function killTask(pid) {
416
419
  }
417
420
  }
418
421
  exports.killTask = killTask;
419
- async function getPid(name) {
420
- const taskCommand = `ps -eo pid,command | grep "${name}" | grep -v grep | awk '{print $1}' | head -1 | xargs echo -n`;
422
+ async function getPid(cmd) {
423
+ const taskCommand = `ps -eo pid,command | grep "${cmd}" | grep -v grep | awk '{print $1}' | head -1 | xargs echo -n`;
421
424
  const pid = await promiseExec(taskCommand);
422
425
  return pid ? Number(pid) : undefined;
423
426
  }
@@ -27,6 +27,7 @@ var DependenceStatus;
27
27
  DependenceStatus[DependenceStatus["removed"] = 4] = "removed";
28
28
  DependenceStatus[DependenceStatus["removeFailed"] = 5] = "removeFailed";
29
29
  DependenceStatus[DependenceStatus["queued"] = 6] = "queued";
30
+ DependenceStatus[DependenceStatus["cancelled"] = 7] = "cancelled";
30
31
  })(DependenceStatus || (exports.DependenceStatus = DependenceStatus = {}));
31
32
  var DependenceTypes;
32
33
  (function (DependenceTypes) {
@@ -8,27 +8,6 @@ const sock_1 = __importDefault(require("./sock"));
8
8
  exports.default = async ({ server }) => {
9
9
  await (0, sock_1.default)({ server });
10
10
  logger_1.default.info('✌️ Sock loaded');
11
- let exitTime = 0;
12
- let timer;
13
- process.on('SIGINT', (singal) => {
14
- logger_1.default.warn(`Server need close, singal ${singal}`);
15
- console.warn(`Server need close, singal ${singal}`);
16
- exitTime++;
17
- if (exitTime >= 3) {
18
- logger_1.default.warn('Forcing server close');
19
- console.warn('Forcing server close');
20
- clearTimeout(timer);
21
- process.exit(1);
22
- }
23
- server.close(() => {
24
- if (timer) {
25
- clearTimeout(timer);
26
- }
27
- timer = setTimeout(() => {
28
- process.exit();
29
- }, 15000);
30
- });
31
- });
32
11
  process.on('uncaughtException', (error) => {
33
12
  logger_1.default.error('Uncaught exception:', error);
34
13
  });
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const body_parser_1 = __importDefault(require("body-parser"));
7
+ const celebrate_1 = require("celebrate");
8
+ const cors_1 = __importDefault(require("cors"));
9
+ const express_jwt_1 = __importDefault(require("express-jwt"));
10
+ const typedi_1 = __importDefault(require("typedi"));
11
+ const config_1 = __importDefault(require("../config"));
12
+ const system_1 = __importDefault(require("../services/system"));
13
+ const logger_1 = __importDefault(require("./logger"));
14
+ exports.default = ({ app }) => {
15
+ app.set('trust proxy', 'loopback');
16
+ app.use((0, cors_1.default)());
17
+ app.use(body_parser_1.default.json({ limit: '50mb' }));
18
+ app.use(body_parser_1.default.urlencoded({ limit: '50mb', extended: true }));
19
+ app.use((0, express_jwt_1.default)({
20
+ secret: config_1.default.secret,
21
+ algorithms: ['HS384'],
22
+ }));
23
+ app.put('/api/reload', async (req, res, next) => {
24
+ try {
25
+ const systemService = typedi_1.default.get(system_1.default);
26
+ const result = await systemService.reloadSystem();
27
+ res.send(result);
28
+ }
29
+ catch (e) {
30
+ logger_1.default.error('🔥 error: %o', e);
31
+ return next(e);
32
+ }
33
+ });
34
+ app.put('/api/system', async (req, res, next) => {
35
+ try {
36
+ const systemService = typedi_1.default.get(system_1.default);
37
+ const result = await systemService.reloadSystem('system');
38
+ res.send(result);
39
+ }
40
+ catch (e) {
41
+ logger_1.default.error('🔥 error: %o', e);
42
+ return next(e);
43
+ }
44
+ });
45
+ app.put('/api/data', async (req, res, next) => {
46
+ try {
47
+ const systemService = typedi_1.default.get(system_1.default);
48
+ const result = await systemService.reloadSystem('data');
49
+ res.send(result);
50
+ }
51
+ catch (e) {
52
+ logger_1.default.error('🔥 error: %o', e);
53
+ return next(e);
54
+ }
55
+ });
56
+ app.use((req, res, next) => {
57
+ const err = new Error('Not Found');
58
+ err['status'] = 404;
59
+ next(err);
60
+ });
61
+ app.use((0, celebrate_1.errors)());
62
+ app.use((err, req, res, next) => {
63
+ if (err.name === 'UnauthorizedError') {
64
+ return res
65
+ .status(err.status)
66
+ .send({ code: 401, message: err.message })
67
+ .end();
68
+ }
69
+ return next(err);
70
+ });
71
+ app.use((err, req, res, next) => {
72
+ res.status(err.status || 500);
73
+ res.json({
74
+ code: err.status || 500,
75
+ message: err.message,
76
+ });
77
+ });
78
+ };
79
+ //# sourceMappingURL=update.js.map
@@ -80,8 +80,11 @@ let DependenceService = class DependenceService {
80
80
  async removeDb(ids) {
81
81
  await dependence_1.DependenceModel.destroy({ where: { id: ids } });
82
82
  }
83
- async dependencies({ searchValue, type }, sort = { position: -1 }, query = {}) {
83
+ async dependencies({ searchValue, type, status, }, sort = [], query = {}) {
84
84
  let condition = Object.assign(Object.assign({}, query), { type: dependence_1.DependenceTypes[type] });
85
+ if (status) {
86
+ condition.status = status.split(',').map(Number);
87
+ }
85
88
  if (searchValue) {
86
89
  const encodeText = encodeURI(searchValue);
87
90
  const reg = {
@@ -93,7 +96,7 @@ let DependenceService = class DependenceService {
93
96
  condition = Object.assign(Object.assign({}, condition), { name: reg });
94
97
  }
95
98
  try {
96
- const result = await this.find(condition);
99
+ const result = await this.find(condition, sort);
97
100
  return result;
98
101
  }
99
102
  catch (error) {
@@ -111,6 +114,24 @@ let DependenceService = class DependenceService {
111
114
  this.installDependenceOneByOne(docs, true, true);
112
115
  return docs;
113
116
  }
117
+ async cancel(ids) {
118
+ const docs = await dependence_1.DependenceModel.findAll({ where: { id: ids } });
119
+ for (const doc of docs) {
120
+ pLimit_1.default.removeQueuedDependency(doc);
121
+ const depInstallCommand = dependence_1.InstallDependenceCommandTypes[doc.type];
122
+ const depUnInstallCommand = dependence_1.unInstallDependenceCommandTypes[doc.type];
123
+ const installCmd = `${depInstallCommand} ${doc.name.trim()}`;
124
+ const unInstallCmd = `${depUnInstallCommand} ${doc.name.trim()}`;
125
+ const pids = await Promise.all([
126
+ (0, util_1.getPid)(installCmd),
127
+ (0, util_1.getPid)(unInstallCmd),
128
+ ]);
129
+ for (const pid of pids) {
130
+ pid && (await (0, util_1.killTask)(pid));
131
+ }
132
+ }
133
+ await dependence_1.DependenceModel.update({ status: dependence_1.DependenceStatus.cancelled }, { where: { id: ids } });
134
+ }
114
135
  async find(query, sort = []) {
115
136
  const docs = await dependence_1.DependenceModel.findAll({
116
137
  where: Object.assign({}, query),
@@ -133,9 +154,13 @@ let DependenceService = class DependenceService {
133
154
  });
134
155
  }
135
156
  installOrUninstallDependency(dependency, isInstall = true, force = false) {
136
- return pLimit_1.default.runOneByOne(() => {
157
+ return pLimit_1.default.runDependeny(dependency, () => {
137
158
  return new Promise(async (resolve) => {
138
159
  var _a;
160
+ if (pLimit_1.default.firstDependencyId !== dependency.id) {
161
+ return resolve(null);
162
+ }
163
+ pLimit_1.default.removeQueuedDependency(dependency);
139
164
  const depIds = [dependency.id];
140
165
  const status = isInstall
141
166
  ? dependence_1.DependenceStatus.installing
@@ -249,7 +274,13 @@ let DependenceService = class DependenceService {
249
274
  ? dependence_1.DependenceStatus.installFailed
250
275
  : dependence_1.DependenceStatus.removeFailed;
251
276
  }
252
- await dependence_1.DependenceModel.update({ status }, { where: { id: depIds } });
277
+ const docs = await dependence_1.DependenceModel.findAll({ where: { id: depIds } });
278
+ const _docIds = docs
279
+ .filter((x) => x.status !== dependence_1.DependenceStatus.cancelled)
280
+ .map((x) => x.id);
281
+ if (_docIds.length > 0) {
282
+ await dependence_1.DependenceModel.update({ status }, { where: { id: _docIds } });
283
+ }
253
284
  // 如果删除依赖成功或者强制删除
254
285
  if ((isSucceed || force) && !isInstall) {
255
286
  this.removeDb(depIds);
@@ -561,16 +561,17 @@ let NotificationService = class NotificationService {
561
561
  }
562
562
  }
563
563
  async webhook() {
564
+ var _a;
564
565
  const { webhookUrl, webhookBody, webhookHeaders, webhookMethod, webhookContentType, } = this.params;
565
- const { formatBody, formatUrl } = this.formatNotifyContent(webhookUrl, webhookBody);
566
- if (!formatUrl && !formatBody) {
566
+ if (!webhookUrl.includes('$title') && !webhookBody.includes('$title')) {
567
567
  throw new Error('Url 或者 Body 中必须包含 $title');
568
568
  }
569
569
  const headers = (0, util_1.parseHeaders)(webhookHeaders);
570
- const body = (0, util_1.parseBody)(formatBody, webhookContentType);
570
+ const body = (0, util_1.parseBody)(webhookBody, webhookContentType, (v) => { var _a; return (_a = v === null || v === void 0 ? void 0 : v.replaceAll('$title', this.title)) === null || _a === void 0 ? void 0 : _a.replaceAll('$content', this.content); });
571
571
  const bodyParam = this.formatBody(webhookContentType, body);
572
572
  const options = Object.assign(Object.assign(Object.assign({ method: webhookMethod, headers }, this.gotOption), { allowGetBody: true }), bodyParam);
573
573
  try {
574
+ const formatUrl = (_a = webhookUrl === null || webhookUrl === void 0 ? void 0 : webhookUrl.replaceAll('$title', encodeURIComponent(this.title))) === null || _a === void 0 ? void 0 : _a.replaceAll('$content', encodeURIComponent(this.content));
574
575
  const res = await (0, got_1.default)(formatUrl, options);
575
576
  if (String(res.statusCode).startsWith('20')) {
576
577
  return true;
@@ -597,16 +598,6 @@ let NotificationService = class NotificationService {
597
598
  }
598
599
  return {};
599
600
  }
600
- formatNotifyContent(url, body) {
601
- var _a, _b;
602
- if (!url.includes('$title') && !body.includes('$title')) {
603
- return {};
604
- }
605
- return {
606
- formatUrl: (_a = url === null || url === void 0 ? void 0 : url.replaceAll('$title', encodeURIComponent(this.title))) === null || _a === void 0 ? void 0 : _a.replaceAll('$content', encodeURIComponent(this.content)),
607
- formatBody: (_b = body === null || body === void 0 ? void 0 : body.replaceAll('$title', this.title)) === null || _b === void 0 ? void 0 : _b.replaceAll('$content', this.content),
608
- };
609
- }
610
601
  };
611
602
  __decorate([
612
603
  (0, typedi_1.Inject)((type) => user_1.default),
@@ -15,23 +15,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
15
15
  return (mod && mod.__esModule) ? mod : { "default": mod };
16
16
  };
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
+ const cross_spawn_1 = require("cross-spawn");
19
+ const fs_1 = __importDefault(require("fs"));
20
+ const got_1 = __importDefault(require("got"));
21
+ const sum_1 = __importDefault(require("lodash/sum"));
22
+ const path_1 = __importDefault(require("path"));
18
23
  const typedi_1 = require("typedi");
19
24
  const winston_1 = __importDefault(require("winston"));
20
25
  const config_1 = __importDefault(require("../config"));
26
+ const const_1 = require("../config/const");
27
+ const util_1 = require("../config/util");
28
+ const dependence_1 = require("../data/dependence");
21
29
  const system_1 = require("../data/system");
30
+ const pLimit_1 = __importDefault(require("../shared/pLimit"));
22
31
  const notify_1 = __importDefault(require("./notify"));
23
32
  const schedule_1 = __importDefault(require("./schedule"));
24
- const cross_spawn_1 = require("cross-spawn");
25
33
  const sock_1 = __importDefault(require("./sock"));
26
- const got_1 = __importDefault(require("got"));
27
- const util_1 = require("../config/util");
28
- const const_1 = require("../config/const");
29
- const pLimit_1 = __importDefault(require("../shared/pLimit"));
30
- const tar_1 = __importDefault(require("tar"));
31
- const path_1 = __importDefault(require("path"));
32
- const fs_1 = __importDefault(require("fs"));
33
- const sum_1 = __importDefault(require("lodash/sum"));
34
- const dependence_1 = require("../data/dependence");
35
34
  let SystemService = class SystemService {
36
35
  constructor(logger, scheduleService, sockService) {
37
36
  this.logger = logger;
@@ -112,7 +111,10 @@ let SystemService = class SystemService {
112
111
  }
113
112
  let command = `cd && ${cmd}`;
114
113
  const docs = await dependence_1.DependenceModel.findAll({
115
- where: { type: dependence_1.DependenceTypes.nodejs, status: dependence_1.DependenceStatus.installed },
114
+ where: {
115
+ type: dependence_1.DependenceTypes.nodejs,
116
+ status: dependence_1.DependenceStatus.installed,
117
+ },
116
118
  });
117
119
  if (docs.length > 0) {
118
120
  command += ` && pnpm i -g`;
@@ -258,24 +260,7 @@ let SystemService = class SystemService {
258
260
  async reloadSystem(target) {
259
261
  const cmd = `real_time=true ql reload ${target || ''}`;
260
262
  const cp = (0, cross_spawn_1.spawn)(cmd, { shell: '/bin/bash' });
261
- cp.stdout.on('data', (data) => {
262
- this.sockService.sendMessage({
263
- type: 'reloadSystem',
264
- message: data.toString(),
265
- });
266
- });
267
- cp.stderr.on('data', (data) => {
268
- this.sockService.sendMessage({
269
- type: 'reloadSystem',
270
- message: data.toString(),
271
- });
272
- });
273
- cp.on('error', (err) => {
274
- this.sockService.sendMessage({
275
- type: 'reloadSystem',
276
- message: JSON.stringify(err),
277
- });
278
- });
263
+ cp.unref();
279
264
  return { code: 200 };
280
265
  }
281
266
  async notify({ title, content }) {
@@ -317,7 +302,7 @@ let SystemService = class SystemService {
317
302
  }
318
303
  async exportData(res) {
319
304
  try {
320
- await tar_1.default.create({ gzip: true, file: config_1.default.dataTgzFile, cwd: config_1.default.rootPath }, ['data']);
305
+ await (0, util_1.promiseExec)(`cd ${config_1.default.rootPath} && tar -zcvf ${config_1.default.dataTgzFile} data/`);
321
306
  res.download(config_1.default.dataTgzFile);
322
307
  }
323
308
  catch (error) {
@@ -327,8 +312,8 @@ let SystemService = class SystemService {
327
312
  async importData() {
328
313
  try {
329
314
  await (0, util_1.promiseExec)(`rm -rf ${path_1.default.join(config_1.default.tmpPath, 'data')}`);
330
- await tar_1.default.x({ file: config_1.default.dataTgzFile, cwd: config_1.default.tmpPath });
331
- return { code: 200 };
315
+ const res = await (0, util_1.promiseExec)(`cd ${config_1.default.tmpPath} && tar -zxvf data.tgz`);
316
+ return { code: 200, data: res };
332
317
  }
333
318
  catch (error) {
334
319
  return { code: 400, message: error.message };
@@ -14,10 +14,16 @@ class TaskLimit {
14
14
  get cronLimitPendingCount() {
15
15
  return this.cronLimit.size;
16
16
  }
17
+ get firstDependencyId() {
18
+ return [...this.queuedDependencyIds.values()][0];
19
+ }
17
20
  constructor() {
18
- this.oneLimit = new p_queue_cjs_1.default({ concurrency: 1 });
21
+ this.dependenyLimit = new p_queue_cjs_1.default({ concurrency: 1 });
22
+ this.queuedDependencyIds = new Set([]);
19
23
  this.updateLogLimit = new p_queue_cjs_1.default({ concurrency: 1 });
20
- this.cronLimit = new p_queue_cjs_1.default({ concurrency: Math.max(os_1.default.cpus().length, 4) });
24
+ this.cronLimit = new p_queue_cjs_1.default({
25
+ concurrency: Math.max(os_1.default.cpus().length, 4),
26
+ });
21
27
  this.setCustomLimit();
22
28
  this.handleEvents();
23
29
  }
@@ -31,7 +37,7 @@ class TaskLimit {
31
37
  this.cronLimit.on('completed', (param) => {
32
38
  logger_1.default.info(`[schedule][任务处理成功] 参数 ${JSON.stringify(param)}`);
33
39
  });
34
- this.cronLimit.on('error', error => {
40
+ this.cronLimit.on('error', (error) => {
35
41
  logger_1.default.error(`[schedule][任务处理错误] 参数 ${JSON.stringify(error)}`);
36
42
  });
37
43
  this.cronLimit.on('next', () => {
@@ -41,6 +47,11 @@ class TaskLimit {
41
47
  logger_1.default.info(`[schedule][任务队列] 空闲中...`);
42
48
  });
43
49
  }
50
+ removeQueuedDependency(dependency) {
51
+ if (this.queuedDependencyIds.has(dependency.id)) {
52
+ this.queuedDependencyIds.delete(dependency.id);
53
+ }
54
+ }
44
55
  async setCustomLimit(limit) {
45
56
  var _a;
46
57
  if (limit) {
@@ -58,8 +69,10 @@ class TaskLimit {
58
69
  async runWithCronLimit(fn, options) {
59
70
  return this.cronLimit.add(fn, options);
60
71
  }
61
- runOneByOne(fn, options) {
62
- return this.oneLimit.add(fn, options);
72
+ runDependeny(dependency, fn, options) {
73
+ this.queuedDependencyIds.add(dependency.id);
74
+ fn.dependency = dependency;
75
+ return this.dependenyLimit.add(fn, options);
63
76
  }
64
77
  updateDepLog(fn, options) {
65
78
  return this.updateLogLimit.add(fn, options);