node-karin 0.11.14 → 0.11.15
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/config/defSet/config.yaml +3 -3
- package/lib/cli/index.d.ts +7 -3
- package/lib/cli/index.js +38 -10
- package/lib/cli/init.js +2 -1
- package/lib/cli/pkg.d.ts +4 -0
- package/lib/cli/pkg.js +14 -0
- package/lib/core/init/config.d.ts +0 -4
- package/lib/core/init/config.js +0 -13
- package/lib/core/listener/listener.js +1 -1
- package/lib/core/process/process.js +1 -5
- package/lib/types/config/config.d.ts +2 -2
- package/lib/utils/index.d.ts +2 -0
- package/lib/utils/index.js +2 -0
- package/lib/utils/tools/exec.d.ts +5 -17
- package/lib/utils/tools/exec.js +28 -26
- package/lib/utils/tools/ffmpeg.d.ts +2 -2
- package/lib/utils/tools/restart.d.ts +15 -0
- package/lib/utils/tools/restart.js +39 -0
- package/lib/utils/tools/stop.d.ts +7 -0
- package/lib/utils/tools/stop.js +13 -0
- package/lib/utils/tools/update.d.ts +26 -84
- package/lib/utils/tools/update.js +40 -28
- package/package.json +1 -1
|
@@ -11,12 +11,12 @@ log4jsCfg:
|
|
|
11
11
|
# 日志文件最大大小 MB
|
|
12
12
|
maxLogSize: 30
|
|
13
13
|
|
|
14
|
-
# 关闭后台进程失败后是否继续启动 继续启动会导致多进程
|
|
15
|
-
multi_progress: false
|
|
16
|
-
|
|
17
14
|
# 控制台触发插件日志颜色 十六进制 默认#FFFF00 不支持热更新
|
|
18
15
|
log_color: "#E1D919"
|
|
19
16
|
|
|
17
|
+
# 重启是否调用pm2 如果不调用则会直接关机 此配置适合有进程守护的程序
|
|
18
|
+
pm2Restart: true
|
|
19
|
+
|
|
20
20
|
# 私聊设置
|
|
21
21
|
private:
|
|
22
22
|
# 关闭私聊后回复的提示词 为空则不回复
|
package/lib/cli/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChildProcess } from 'child_process';
|
|
1
|
+
import { ChildProcess, ExecOptions } from 'child_process';
|
|
2
2
|
export declare const enum Runner {
|
|
3
3
|
Node = "node",
|
|
4
4
|
Tsx = "tsx",
|
|
@@ -19,7 +19,7 @@ export declare class KarinCli {
|
|
|
19
19
|
file: string;
|
|
20
20
|
constructor();
|
|
21
21
|
/**
|
|
22
|
-
* 获取pkg
|
|
22
|
+
* 获取pkg配置
|
|
23
23
|
* @param isNpm - 是否是npm包
|
|
24
24
|
*/
|
|
25
25
|
pkg(isNpm: boolean): any;
|
|
@@ -73,11 +73,15 @@ export declare class KarinCli {
|
|
|
73
73
|
* @param pkg - 包管理器
|
|
74
74
|
*/
|
|
75
75
|
getRemoteVersion(name: string, pkg: 'pnpm' | 'cnpm' | 'yarn' | 'npm'): Promise<string>;
|
|
76
|
+
/**
|
|
77
|
+
* 获取git插件列表
|
|
78
|
+
*/
|
|
79
|
+
getGitPlugins(): Array<string>;
|
|
76
80
|
/**
|
|
77
81
|
* 封装exec
|
|
78
82
|
* @param cmd - 命令
|
|
79
83
|
*/
|
|
80
|
-
exec(cmd: string): Promise<string>;
|
|
84
|
+
exec(cmd: string, options?: ExecOptions): Promise<string>;
|
|
81
85
|
/**
|
|
82
86
|
* 封装axios 超时返回false
|
|
83
87
|
* @param url - 请求地址
|
package/lib/cli/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import path from 'path';
|
|
|
3
3
|
import yaml from 'yaml';
|
|
4
4
|
import axios from 'axios';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
|
+
import { getRegistry } from './pkg.js';
|
|
6
7
|
import { exec as execCmd, spawn } from 'child_process';
|
|
7
|
-
import { KarinCfgInit } from '../core/init/config.js';
|
|
8
8
|
export class KarinCli {
|
|
9
9
|
child;
|
|
10
10
|
filename;
|
|
@@ -20,10 +20,11 @@ export class KarinCli {
|
|
|
20
20
|
/** 入口文件(注意后缀) */
|
|
21
21
|
this.file = path.join(path.dirname(this.filename), '../index.js');
|
|
22
22
|
this.child = null;
|
|
23
|
+
process.env.karin_app_pkg = getRegistry();
|
|
23
24
|
process.env.karin_app_version = this.pkg(true).version;
|
|
24
25
|
}
|
|
25
26
|
/**
|
|
26
|
-
* 获取pkg
|
|
27
|
+
* 获取pkg配置
|
|
27
28
|
* @param isNpm - 是否是npm包
|
|
28
29
|
*/
|
|
29
30
|
pkg(isNpm) {
|
|
@@ -187,9 +188,8 @@ export class KarinCli {
|
|
|
187
188
|
];
|
|
188
189
|
const list = Object.keys(this.pkg(false).dependencies).filter(key => !pkgdependencies.includes(key));
|
|
189
190
|
/** 获取包管理器 */
|
|
190
|
-
const pkg =
|
|
191
|
+
const pkg = getRegistry();
|
|
191
192
|
const cmd = pkg === 'yarn' ? 'yarn upgrade' : `${pkg} update`;
|
|
192
|
-
/** 异步并发更新依赖 */
|
|
193
193
|
await Promise.all(list.map(async (item) => {
|
|
194
194
|
try {
|
|
195
195
|
/** 检查是否已经是最新版本 */
|
|
@@ -205,11 +205,26 @@ export class KarinCli {
|
|
|
205
205
|
}
|
|
206
206
|
catch (error) {
|
|
207
207
|
console.error(`[依赖更新] ${item} 更新失败:`);
|
|
208
|
-
console.error(
|
|
209
|
-
console.error(`error.message: ${error.message}`);
|
|
208
|
+
console.error(error.stack || error.message || error);
|
|
210
209
|
}
|
|
211
210
|
}));
|
|
212
|
-
console.log('
|
|
211
|
+
console.log('[依赖更新] 所有npm依赖已更新完成~');
|
|
212
|
+
console.log('[依赖更新] 开始更新git插件...');
|
|
213
|
+
const gitList = this.getGitPlugins();
|
|
214
|
+
if (!gitList.length)
|
|
215
|
+
return console.log('[依赖更新] 没有git插件需要更新~');
|
|
216
|
+
await Promise.all(gitList.map(async (item) => {
|
|
217
|
+
const dir = path.resolve(process.cwd(), 'plugins', item);
|
|
218
|
+
try {
|
|
219
|
+
await this.exec('git pull', { cwd: dir });
|
|
220
|
+
console.log(`[依赖更新] ${item} 更新完成~`);
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
console.error(`[依赖更新] ${item} 更新失败`);
|
|
224
|
+
console.error(error.stack || error.message || error);
|
|
225
|
+
}
|
|
226
|
+
}));
|
|
227
|
+
console.log('[依赖更新] 所有git插件已更新完成~');
|
|
213
228
|
}
|
|
214
229
|
/**
|
|
215
230
|
* 获取指定包的本地版本
|
|
@@ -246,15 +261,28 @@ export class KarinCli {
|
|
|
246
261
|
}
|
|
247
262
|
return text.trim();
|
|
248
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* 获取git插件列表
|
|
266
|
+
*/
|
|
267
|
+
getGitPlugins() {
|
|
268
|
+
const dir = path.resolve(process.cwd(), 'plugins');
|
|
269
|
+
let list = fs.readdirSync(dir, { withFileTypes: true });
|
|
270
|
+
/** 忽略非文件夹、非 karin-plugin-开头的文件夹 */
|
|
271
|
+
list = list.filter(v => v.isDirectory() && v.name.startsWith('karin-plugin-'));
|
|
272
|
+
list = list.filter(v => fs.existsSync(`${dir}/${v.name}/package.json`));
|
|
273
|
+
const arr = [];
|
|
274
|
+
list.map(v => arr.push(v.name));
|
|
275
|
+
return arr;
|
|
276
|
+
}
|
|
249
277
|
/**
|
|
250
278
|
* 封装exec
|
|
251
279
|
* @param cmd - 命令
|
|
252
280
|
*/
|
|
253
|
-
exec(cmd) {
|
|
281
|
+
exec(cmd, options) {
|
|
254
282
|
return new Promise((resolve, reject) => {
|
|
255
|
-
execCmd(cmd, (error, stdout, stderr) => {
|
|
283
|
+
execCmd(cmd, options, (error, stdout, stderr) => {
|
|
256
284
|
if (stdout)
|
|
257
|
-
return resolve(stdout.trim());
|
|
285
|
+
return resolve(stdout.toString().trim());
|
|
258
286
|
if (error)
|
|
259
287
|
return reject(error);
|
|
260
288
|
return reject(stderr);
|
package/lib/cli/init.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { getRegistry } from './pkg.js';
|
|
2
3
|
import { KarinCfgInit } from '../core/init/config.js';
|
|
3
4
|
/**
|
|
4
5
|
* 休眠函数
|
|
@@ -14,7 +15,7 @@ async function main() {
|
|
|
14
15
|
const init = new KarinCfgInit();
|
|
15
16
|
init.init();
|
|
16
17
|
await sleep(1000);
|
|
17
|
-
const pkg =
|
|
18
|
+
const pkg = getRegistry();
|
|
18
19
|
/** 结果 */
|
|
19
20
|
await init.install(pkg);
|
|
20
21
|
}
|
package/lib/cli/pkg.d.ts
ADDED
package/lib/cli/pkg.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
/**
|
|
3
|
+
* 获取当前的包管理器 根据锁文件判断 优先级 pnpm > yarn > npm > cnpm
|
|
4
|
+
*/
|
|
5
|
+
export const getRegistry = () => {
|
|
6
|
+
if (fs.existsSync('./pnpm-lock.yaml'))
|
|
7
|
+
return 'pnpm';
|
|
8
|
+
if (fs.existsSync('./yarn.lock'))
|
|
9
|
+
return 'yarn';
|
|
10
|
+
if (fs.existsSync('./package-lock.json'))
|
|
11
|
+
return 'npm';
|
|
12
|
+
// cnpm 没有锁文件
|
|
13
|
+
return 'cnpm';
|
|
14
|
+
};
|
package/lib/core/init/config.js
CHANGED
|
@@ -198,17 +198,4 @@ export class KarinCfgInit {
|
|
|
198
198
|
});
|
|
199
199
|
});
|
|
200
200
|
}
|
|
201
|
-
/**
|
|
202
|
-
* 获取当前的包管理器 根据锁文件判断
|
|
203
|
-
*/
|
|
204
|
-
getRegistry() {
|
|
205
|
-
if (fs.existsSync('./pnpm-lock.yaml'))
|
|
206
|
-
return 'pnpm';
|
|
207
|
-
if (fs.existsSync('./yarn.lock'))
|
|
208
|
-
return 'yarn';
|
|
209
|
-
if (fs.existsSync('./package-lock.json'))
|
|
210
|
-
return 'npm';
|
|
211
|
-
// cnpm 没有锁文件
|
|
212
|
-
return 'cnpm';
|
|
213
|
-
}
|
|
214
201
|
}
|
|
@@ -71,7 +71,7 @@ export class Listeners extends EventEmitter {
|
|
|
71
71
|
}
|
|
72
72
|
const element = [
|
|
73
73
|
segment.reply(message_id),
|
|
74
|
-
segment.text(
|
|
74
|
+
segment.text(`\nKarin 重启成功:${restartTime}秒`),
|
|
75
75
|
];
|
|
76
76
|
await this.sendMsg(id, contact, element);
|
|
77
77
|
await level.del(key);
|
|
@@ -74,11 +74,7 @@ export default class Process {
|
|
|
74
74
|
* 根据配置文件判断是否继续
|
|
75
75
|
*/
|
|
76
76
|
logger.error(logger.red(`后台进程关闭失败,请检查是否有进程正在占用端口${config.Server.http.port}`));
|
|
77
|
-
|
|
78
|
-
logger.error(logger.red('当前配置不允许多进程运行,程序即将退出'));
|
|
79
|
-
await this.exit(1);
|
|
80
|
-
}
|
|
81
|
-
logger.error(logger.red('当前配置允许多进程运行,程序继续运行'));
|
|
77
|
+
await this.exit();
|
|
82
78
|
return this;
|
|
83
79
|
}
|
|
84
80
|
/**
|
package/lib/utils/index.d.ts
CHANGED
package/lib/utils/index.js
CHANGED
|
@@ -1,32 +1,20 @@
|
|
|
1
|
+
import { ExecOptions } from 'child_process';
|
|
1
2
|
/**
|
|
2
3
|
* 执行 shell 命令
|
|
3
4
|
* @param cmd 命令
|
|
4
5
|
* @param log 是否打印日志
|
|
5
6
|
* @param options 选项
|
|
6
7
|
*/
|
|
7
|
-
export declare const exec: (cmd: string, log?: boolean, options?: {
|
|
8
|
-
cwd: string;
|
|
9
|
-
encoding: string;
|
|
10
|
-
}) => Promise<{
|
|
11
|
-
/**
|
|
12
|
-
* - 执行状态
|
|
13
|
-
*/
|
|
8
|
+
export declare const exec: (cmd: string, log?: boolean, options?: ExecOptions) => Promise<{
|
|
14
9
|
status: "ok" | "failed";
|
|
15
|
-
/**
|
|
16
|
-
* - 错误信息
|
|
17
|
-
*/
|
|
18
10
|
error: Error | null;
|
|
19
|
-
stdout: string
|
|
20
|
-
stderr: string
|
|
11
|
+
stdout: string;
|
|
12
|
+
stderr: string;
|
|
21
13
|
}>;
|
|
22
14
|
/**
|
|
23
15
|
* 执行 shell 命令
|
|
24
16
|
* @param cmd 命令
|
|
25
|
-
* @param log 是否打印日志
|
|
26
17
|
* @param options 选项
|
|
27
18
|
*/
|
|
28
|
-
export declare const execs: (cmd: string, options?:
|
|
29
|
-
cwd: string;
|
|
30
|
-
encoding: string;
|
|
31
|
-
}) => Promise<string>;
|
|
19
|
+
export declare const execs: (cmd: string, options?: ExecOptions) => Promise<string>;
|
|
32
20
|
export default exec;
|
package/lib/utils/tools/exec.js
CHANGED
|
@@ -6,41 +6,43 @@ import { exec as execCmd } from 'child_process';
|
|
|
6
6
|
* @param log 是否打印日志
|
|
7
7
|
* @param options 选项
|
|
8
8
|
*/
|
|
9
|
-
export const exec = (cmd, log = true, options = { cwd: process.cwd()
|
|
9
|
+
export const exec = async (cmd, log = true, options = { cwd: process.cwd() }) => {
|
|
10
|
+
const logType = (status) => ({
|
|
11
|
+
start: '[exec][开始执行]',
|
|
12
|
+
ok: '[exec][执行成功]',
|
|
13
|
+
failed: '[exec][执行失败]',
|
|
14
|
+
})[status];
|
|
15
|
+
const logMessage = (status, details = '') => {
|
|
16
|
+
if (log) {
|
|
17
|
+
const colorFunc = {
|
|
18
|
+
start: logger.yellow,
|
|
19
|
+
ok: logger.green,
|
|
20
|
+
failed: logger.red,
|
|
21
|
+
}[status];
|
|
22
|
+
logger.info([
|
|
23
|
+
colorFunc(logType(status)),
|
|
24
|
+
`cmd: ${cmd}`,
|
|
25
|
+
`cwd: ${options.cwd}`,
|
|
26
|
+
details,
|
|
27
|
+
'--------',
|
|
28
|
+
].join('\n'));
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
logMessage('start');
|
|
10
32
|
return new Promise(resolve => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const logType = (status) => {
|
|
16
|
-
switch (status) {
|
|
17
|
-
case '开始执行':
|
|
18
|
-
return logger.yellow('[exec][开始执行]');
|
|
19
|
-
case 'ok':
|
|
20
|
-
return logger.green('[exec][执行成功]');
|
|
21
|
-
case 'failed':
|
|
22
|
-
return logger.red('[exec][执行失败]');
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
const formatMessage = (status, details) => [logType(status), `cmd: ${cmd}`, `cwd: ${options.cwd || process.cwd()}`, details, '--------'].join('\n');
|
|
26
|
-
logMessage('info', formatMessage('开始执行', ''));
|
|
27
|
-
execCmd(cmd, options, (error, stdout, stderr) => {
|
|
28
|
-
if (error) {
|
|
29
|
-
logMessage('error', formatMessage('failed', `Error: ${error.message || error.stack || error.toString()}`));
|
|
30
|
-
return resolve({ status: 'failed', error, stdout, stderr });
|
|
31
|
-
}
|
|
32
|
-
logMessage('mark', formatMessage('ok', `stdout: ${stdout}\nstderr: ${stderr}`));
|
|
33
|
-
resolve({ status: 'ok', error, stdout, stderr });
|
|
33
|
+
execCmd(cmd, options, (error, stdout = '', stderr = '') => {
|
|
34
|
+
const status = error ? 'failed' : 'ok';
|
|
35
|
+
logMessage(status, error ? `Error: ${error.message}` : `stdout: ${stdout}\nstderr: ${stderr}`);
|
|
36
|
+
resolve({ status, error, stdout, stderr });
|
|
34
37
|
});
|
|
35
38
|
});
|
|
36
39
|
};
|
|
37
40
|
/**
|
|
38
41
|
* 执行 shell 命令
|
|
39
42
|
* @param cmd 命令
|
|
40
|
-
* @param log 是否打印日志
|
|
41
43
|
* @param options 选项
|
|
42
44
|
*/
|
|
43
|
-
export const execs = (cmd, options = { cwd: process.cwd()
|
|
45
|
+
export const execs = (cmd, options = { cwd: process.cwd() }) => {
|
|
44
46
|
return new Promise((resolve, reject) => {
|
|
45
47
|
execCmd(cmd, options, (error, stdout) => {
|
|
46
48
|
if (error)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Contact } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* 重启Bot
|
|
4
|
+
* @param self_id - 机器人的id 传e.self_id
|
|
5
|
+
* @param contact - 事件联系人信息 也就是从哪来的这条消息 传e.contact即可
|
|
6
|
+
* @param message_id - 消息id 传e.message_id
|
|
7
|
+
* @param isFront - 是否为前台重启 默认是
|
|
8
|
+
*/
|
|
9
|
+
export declare const restart: (self_id: string, contact: Contact, message_id: string, isFront?: boolean) => Promise<{
|
|
10
|
+
status: string;
|
|
11
|
+
data: string;
|
|
12
|
+
} | {
|
|
13
|
+
status: string;
|
|
14
|
+
data: Error | null;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import exec from './exec.js';
|
|
2
|
+
import { level } from '../../db/index.js';
|
|
3
|
+
import { config } from '../config/config.js';
|
|
4
|
+
/**
|
|
5
|
+
* 重启Bot
|
|
6
|
+
* @param self_id - 机器人的id 传e.self_id
|
|
7
|
+
* @param contact - 事件联系人信息 也就是从哪来的这条消息 传e.contact即可
|
|
8
|
+
* @param message_id - 消息id 传e.message_id
|
|
9
|
+
* @param isFront - 是否为前台重启 默认是
|
|
10
|
+
*/
|
|
11
|
+
export const restart = async (self_id, contact, message_id, isFront = true) => {
|
|
12
|
+
const options = {
|
|
13
|
+
id: self_id,
|
|
14
|
+
contact,
|
|
15
|
+
message_id,
|
|
16
|
+
time: Date.now(),
|
|
17
|
+
};
|
|
18
|
+
const key = `karin:restart:${options.id}`;
|
|
19
|
+
await level.set(key, options);
|
|
20
|
+
if (isFront) {
|
|
21
|
+
if (!process.send)
|
|
22
|
+
return { status: 'failed', data: '前台重启失败,当前环境不支持,仅支持【npx karin start】启动的环境' };
|
|
23
|
+
process.send({ action: 'result', env: process.env });
|
|
24
|
+
process.exit();
|
|
25
|
+
}
|
|
26
|
+
if (!config.Config.pm2Restart)
|
|
27
|
+
process.exit();
|
|
28
|
+
if (process.env.pm_id) {
|
|
29
|
+
const pm2 = await exec('npx karin rs');
|
|
30
|
+
if (pm2.status === 'ok')
|
|
31
|
+
process.exit();
|
|
32
|
+
return { status: 'failed', data: pm2.error };
|
|
33
|
+
}
|
|
34
|
+
/** 调用pm2启动 */
|
|
35
|
+
const pm2 = await exec('npx karin pm2');
|
|
36
|
+
if (pm2.status === 'ok')
|
|
37
|
+
process.exit();
|
|
38
|
+
return { status: 'failed', data: pm2.error };
|
|
39
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import exec from './exec.js';
|
|
2
|
+
/**
|
|
3
|
+
* 停止Bot
|
|
4
|
+
*/
|
|
5
|
+
export const stop = async () => {
|
|
6
|
+
if (process.env.pm_id) {
|
|
7
|
+
const pm2 = await exec('pm2 delete ' + process.env.pm_id);
|
|
8
|
+
if (pm2.status === 'ok')
|
|
9
|
+
process.exit();
|
|
10
|
+
return { status: 'failed', data: pm2.error };
|
|
11
|
+
}
|
|
12
|
+
process.exit();
|
|
13
|
+
};
|
|
@@ -1,75 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const update: {
|
|
1
|
+
export declare class Updates {
|
|
3
2
|
dir: string;
|
|
3
|
+
constructor();
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
* @param
|
|
7
|
-
* @param
|
|
8
|
-
* @param time - 超时时间 默认120s
|
|
9
|
-
*/
|
|
10
|
-
update(path: string, cmd?: string, time?: number): Promise<{
|
|
11
|
-
status: string;
|
|
12
|
-
data: string;
|
|
13
|
-
}>;
|
|
14
|
-
/**
|
|
15
|
-
* 获取指定仓库最后一次提交时间日期
|
|
16
|
-
* @param path - 插件相对路径
|
|
17
|
-
*/
|
|
18
|
-
getTime(path: string): Promise<string>;
|
|
19
|
-
/**
|
|
20
|
-
* 获取指定仓库最后一次提交哈希值
|
|
21
|
-
* @param {string} path - 插件相对路径
|
|
22
|
-
* @param {boolean} [short] - 是否获取短哈希 默认true
|
|
23
|
-
* @returns {Promise<string>}
|
|
24
|
-
*/
|
|
25
|
-
getHash(path: string, short?: boolean): Promise<string>;
|
|
26
|
-
/**
|
|
27
|
-
* 获取指定仓库的提交记录
|
|
28
|
-
* @param {{
|
|
29
|
-
* path: string,
|
|
30
|
-
* count?: number,
|
|
31
|
-
* hash?: string
|
|
32
|
-
* }} options - 参数
|
|
33
|
-
* @param {string} options.path - 插件相对路径
|
|
34
|
-
* @param {number} [options.count] - 获取日志条数 默认1条
|
|
35
|
-
* @param {string} [options.hash] - 指定HEAD
|
|
36
|
-
* @returns {Promise<string>}
|
|
5
|
+
* 更新npm包
|
|
6
|
+
* @param name - 包名
|
|
7
|
+
* @param timeout - 超时时间 默认120s
|
|
37
8
|
*/
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
count?: any;
|
|
41
|
-
hash?: any;
|
|
42
|
-
branch?: any;
|
|
43
|
-
}): Promise<string>;
|
|
44
|
-
/**
|
|
45
|
-
* 检查插件是否有更新
|
|
46
|
-
* @param {string} path - 插件相对路径
|
|
47
|
-
* @param {number} [time] - 超时时间 默认120s
|
|
48
|
-
* @returns {Promise<{status: 'ok'|'failed', data: string|boolean}>}
|
|
49
|
-
*/
|
|
50
|
-
checkUpdate(path: fs.PathLike, time?: number): Promise<{
|
|
51
|
-
status: string;
|
|
52
|
-
data: string | undefined;
|
|
53
|
-
count?: undefined;
|
|
54
|
-
} | {
|
|
55
|
-
status: string;
|
|
56
|
-
data: boolean;
|
|
57
|
-
count?: undefined;
|
|
58
|
-
} | {
|
|
59
|
-
status: string;
|
|
9
|
+
updatePkg(name: string, timeout?: number): Promise<{
|
|
10
|
+
status: boolean;
|
|
60
11
|
data: string;
|
|
61
|
-
count: string | number;
|
|
62
12
|
}>;
|
|
63
|
-
};
|
|
64
|
-
export declare const Update: {
|
|
65
|
-
dir: string;
|
|
66
13
|
/**
|
|
67
14
|
* 更新框架或插件
|
|
68
15
|
* @param path - 插件相对路径
|
|
69
16
|
* @param cmd - 更新命令 默认git pull
|
|
70
|
-
* @param
|
|
17
|
+
* @param timeout - 超时时间 默认120s
|
|
71
18
|
*/
|
|
72
|
-
update(path: string, cmd?: string,
|
|
19
|
+
update(path: string, cmd?: string, timeout?: number): Promise<{
|
|
73
20
|
status: string;
|
|
74
21
|
data: string;
|
|
75
22
|
}>;
|
|
@@ -80,36 +27,29 @@ export declare const Update: {
|
|
|
80
27
|
getTime(path: string): Promise<string>;
|
|
81
28
|
/**
|
|
82
29
|
* 获取指定仓库最后一次提交哈希值
|
|
83
|
-
* @param
|
|
84
|
-
* @param
|
|
85
|
-
* @returns {Promise<string>}
|
|
30
|
+
* @param path - 插件相对路径
|
|
31
|
+
* @param short - 是否获取短哈希 默认true
|
|
86
32
|
*/
|
|
87
33
|
getHash(path: string, short?: boolean): Promise<string>;
|
|
88
34
|
/**
|
|
89
35
|
* 获取指定仓库的提交记录
|
|
90
|
-
* @param {{
|
|
91
|
-
* path: string,
|
|
92
|
-
* count?: number,
|
|
93
|
-
* hash?: string
|
|
94
|
-
* }} options - 参数
|
|
95
|
-
* @param {string} options.path - 插件相对路径
|
|
96
|
-
* @param {number} [options.count] - 获取日志条数 默认1条
|
|
97
|
-
* @param {string} [options.hash] - 指定HEAD
|
|
98
|
-
* @returns {Promise<string>}
|
|
99
36
|
*/
|
|
100
37
|
getCommit(options: {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
38
|
+
/** 指令命令路径 */
|
|
39
|
+
path: string;
|
|
40
|
+
/** 获取几次提交 默认1次 */
|
|
41
|
+
count?: number;
|
|
42
|
+
/** 指定哈希 */
|
|
43
|
+
hash?: string;
|
|
44
|
+
/** 指定分支 */
|
|
45
|
+
branch?: string;
|
|
105
46
|
}): Promise<string>;
|
|
106
47
|
/**
|
|
107
48
|
* 检查插件是否有更新
|
|
108
|
-
* @param
|
|
109
|
-
* @param
|
|
110
|
-
* @returns {Promise<{status: 'ok'|'failed', data: string|boolean}>}
|
|
49
|
+
* @param path - 插件相对路径
|
|
50
|
+
* @param time - 超时时间 默认120s
|
|
111
51
|
*/
|
|
112
|
-
checkUpdate(path:
|
|
52
|
+
checkUpdate(path: string, time?: number): Promise<{
|
|
113
53
|
status: string;
|
|
114
54
|
data: string | undefined;
|
|
115
55
|
count?: undefined;
|
|
@@ -120,6 +60,8 @@ export declare const Update: {
|
|
|
120
60
|
} | {
|
|
121
61
|
status: string;
|
|
122
62
|
data: string;
|
|
123
|
-
count:
|
|
63
|
+
count: number;
|
|
124
64
|
}>;
|
|
125
|
-
}
|
|
65
|
+
}
|
|
66
|
+
export declare const update: Updates;
|
|
67
|
+
export declare const Update: Updates;
|
|
@@ -1,17 +1,39 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import exec from './exec.js';
|
|
3
|
-
|
|
3
|
+
import { KarinCli } from '../../cli/index.js';
|
|
4
|
+
import { getRegistry } from '../../cli/pkg.js';
|
|
5
|
+
export class Updates {
|
|
4
6
|
dir;
|
|
5
7
|
constructor() {
|
|
6
8
|
this.dir = './plugins';
|
|
7
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* 更新npm包
|
|
12
|
+
* @param name - 包名
|
|
13
|
+
* @param timeout - 超时时间 默认120s
|
|
14
|
+
*/
|
|
15
|
+
async updatePkg(name, timeout = 120) {
|
|
16
|
+
const pkg = getRegistry();
|
|
17
|
+
const cmd = (pkg === 'yarn' ? 'yarn upgrade' : `${pkg} update`) + `${name}@latest`;
|
|
18
|
+
/** 检查是否已经是最新版本 */
|
|
19
|
+
const tools = new KarinCli();
|
|
20
|
+
const local = await tools.getLocalVersion(name, pkg);
|
|
21
|
+
const remote = await tools.getRemoteVersion(name, pkg);
|
|
22
|
+
logger.info(`[依赖更新] ${name} 当前版本: ${local} 最新版本: ${remote}`);
|
|
23
|
+
if (local === remote)
|
|
24
|
+
return { status: true, data: `${name} 已经是最新版本~` };
|
|
25
|
+
const npm = await exec(cmd, true, { cwd: process.cwd(), timeout: timeout * 1000 });
|
|
26
|
+
if (npm.status === 'ok')
|
|
27
|
+
return { status: true, data: `${name} 更新完成~` };
|
|
28
|
+
return { status: false, data: `${name} 更新失败: ${npm.error?.message}` };
|
|
29
|
+
}
|
|
8
30
|
/**
|
|
9
31
|
* 更新框架或插件
|
|
10
32
|
* @param path - 插件相对路径
|
|
11
33
|
* @param cmd - 更新命令 默认git pull
|
|
12
|
-
* @param
|
|
34
|
+
* @param timeout - 超时时间 默认120s
|
|
13
35
|
*/
|
|
14
|
-
async update(path, cmd = 'git pull',
|
|
36
|
+
async update(path, cmd = 'git pull', timeout = 120) {
|
|
15
37
|
/** 检查一下路径是否存在 */
|
|
16
38
|
if (!fs.existsSync(path))
|
|
17
39
|
return { status: 'failed', data: '路径不存在' };
|
|
@@ -21,7 +43,7 @@ export const update = new (class Update {
|
|
|
21
43
|
/** 设置超时时间 */
|
|
22
44
|
const timer = setTimeout(() => {
|
|
23
45
|
return { status: 'failed', data: '执行超时' };
|
|
24
|
-
},
|
|
46
|
+
}, timeout * 1000);
|
|
25
47
|
const options = { env: process.env, cwd: path, encoding: 'utf-8' };
|
|
26
48
|
/** 记录当前短哈希 */
|
|
27
49
|
const hash = await this.getHash(path);
|
|
@@ -36,17 +58,17 @@ export const update = new (class Update {
|
|
|
36
58
|
const time = await this.getTime(path);
|
|
37
59
|
return {
|
|
38
60
|
status: 'ok',
|
|
39
|
-
data:
|
|
61
|
+
data: `\n当前版本已是最新版本\n最后更新时间:${time}\n更新详情:${await this.getCommit({ path, count: 1 })}`,
|
|
40
62
|
};
|
|
41
63
|
}
|
|
42
64
|
const Commit = await this.getCommit({ path, hash });
|
|
43
65
|
return {
|
|
44
66
|
status: 'ok',
|
|
45
|
-
data:
|
|
67
|
+
data: `\n更新成功\n更新日志:\n${Commit}`,
|
|
46
68
|
};
|
|
47
69
|
}
|
|
48
|
-
const
|
|
49
|
-
return { status: 'failed', data
|
|
70
|
+
const data = `\n更新失败\n错误信息:${error?.stack?.toString() || error?.message?.toString() || error?.toString() || error}\n请解决错误后重试或执行【#强制更新】`;
|
|
71
|
+
return { status: 'failed', data };
|
|
50
72
|
}
|
|
51
73
|
/**
|
|
52
74
|
* 获取指定仓库最后一次提交时间日期
|
|
@@ -54,20 +76,19 @@ export const update = new (class Update {
|
|
|
54
76
|
*/
|
|
55
77
|
async getTime(path) {
|
|
56
78
|
const cmd = 'git log -1 --format=%cd --date=format:"%Y-%m-%d %H:%M:%S"';
|
|
57
|
-
const data = await exec(cmd, false, { cwd: path
|
|
79
|
+
const data = await exec(cmd, false, { cwd: path });
|
|
58
80
|
if (data.status === 'failed')
|
|
59
81
|
return '获取时间失败,请重试或更新Git~';
|
|
60
82
|
return data.stdout.trim();
|
|
61
83
|
}
|
|
62
84
|
/**
|
|
63
85
|
* 获取指定仓库最后一次提交哈希值
|
|
64
|
-
* @param
|
|
65
|
-
* @param
|
|
66
|
-
* @returns {Promise<string>}
|
|
86
|
+
* @param path - 插件相对路径
|
|
87
|
+
* @param short - 是否获取短哈希 默认true
|
|
67
88
|
*/
|
|
68
89
|
async getHash(path, short = true) {
|
|
69
90
|
const cmd = short ? 'git rev-parse --short HEAD' : 'git rev-parse HEAD';
|
|
70
|
-
const data = await exec(cmd, false, { cwd: path
|
|
91
|
+
const data = await exec(cmd, false, { cwd: path });
|
|
71
92
|
if (data.status === 'failed') {
|
|
72
93
|
const text = data.error;
|
|
73
94
|
throw new Error(text);
|
|
@@ -76,15 +97,6 @@ export const update = new (class Update {
|
|
|
76
97
|
}
|
|
77
98
|
/**
|
|
78
99
|
* 获取指定仓库的提交记录
|
|
79
|
-
* @param {{
|
|
80
|
-
* path: string,
|
|
81
|
-
* count?: number,
|
|
82
|
-
* hash?: string
|
|
83
|
-
* }} options - 参数
|
|
84
|
-
* @param {string} options.path - 插件相对路径
|
|
85
|
-
* @param {number} [options.count] - 获取日志条数 默认1条
|
|
86
|
-
* @param {string} [options.hash] - 指定HEAD
|
|
87
|
-
* @returns {Promise<string>}
|
|
88
100
|
*/
|
|
89
101
|
async getCommit(options) {
|
|
90
102
|
const { path, count = 1, hash, branch } = options;
|
|
@@ -95,7 +107,7 @@ export const update = new (class Update {
|
|
|
95
107
|
/** 指定分支 */
|
|
96
108
|
if (branch)
|
|
97
109
|
cmd = `git log -${count} ${branch} --format="[%ad] %s %n" --date="format:%m-%d %H:%M"`;
|
|
98
|
-
const data = await exec(cmd, false, { cwd: path
|
|
110
|
+
const data = await exec(cmd, false, { cwd: path });
|
|
99
111
|
if (data.status === 'failed') {
|
|
100
112
|
const text = data.error;
|
|
101
113
|
throw new Error(text);
|
|
@@ -104,9 +116,8 @@ export const update = new (class Update {
|
|
|
104
116
|
}
|
|
105
117
|
/**
|
|
106
118
|
* 检查插件是否有更新
|
|
107
|
-
* @param
|
|
108
|
-
* @param
|
|
109
|
-
* @returns {Promise<{status: 'ok'|'failed', data: string|boolean}>}
|
|
119
|
+
* @param path - 插件相对路径
|
|
120
|
+
* @param time - 超时时间 默认120s
|
|
110
121
|
*/
|
|
111
122
|
async checkUpdate(path, time = 120) {
|
|
112
123
|
/** 检查一下路径是否存在 */
|
|
@@ -131,9 +142,10 @@ export const update = new (class Update {
|
|
|
131
142
|
if (stdout.includes('Your branch is up to date with'))
|
|
132
143
|
return { status: 'ok', data: false };
|
|
133
144
|
/** 获取落后几次更新 */
|
|
134
|
-
const count = stdout.match(/Your branch is behind '.*' by (\d+) commits/)?.[1] || 1;
|
|
145
|
+
const count = Number(stdout.match(/Your branch is behind '.*' by (\d+) commits/)?.[1]) || 1;
|
|
135
146
|
const data = await this.getCommit({ path, count, branch: 'origin' });
|
|
136
147
|
return { status: 'ok', data, count };
|
|
137
148
|
}
|
|
138
|
-
}
|
|
149
|
+
}
|
|
150
|
+
export const update = new Updates();
|
|
139
151
|
export const Update = update;
|