1 | import { existsSync } from 'fs';
|
2 | import { join } from 'path';
|
3 | import chalk from 'chalk';
|
4 | import { get } from 'lodash';
|
5 |
|
6 | import Feflow from '../core';
|
7 | import { Config } from '../shared/file';
|
8 | import CommandPicker, { COMMAND_TYPE } from '../core/command-picker';
|
9 |
|
10 | type PrintError = {
|
11 | error: any | Error;
|
12 | msg: string;
|
13 | pluginPath?: string;
|
14 | hideError?: boolean;
|
15 | };
|
16 |
|
17 |
|
18 | export class FefError {
|
19 | context: Feflow;
|
20 | picker: CommandPicker | null;
|
21 |
|
22 | defaultDocs = 'https://github.com/Tencent/feflow/issues';
|
23 | docsPathList = ['docs', 'doc', 'bugs.url', 'repository.url'];
|
24 | pluginFile = 'package.json';
|
25 | unversalpluginFile = ['plugin.yaml', 'plugin.yml'];
|
26 |
|
27 | constructor(context: Feflow) {
|
28 | this.context = context;
|
29 |
|
30 |
|
31 |
|
32 | if (this.context.commandPick) {
|
33 | this.picker = context.commandPick as CommandPicker;
|
34 | } else {
|
35 | this.picker = null;
|
36 |
|
37 | context.logger.debug('command pick is not inital');
|
38 | }
|
39 | }
|
40 |
|
41 | checkPick() {
|
42 | if (this.picker) return true;
|
43 | if (this.context.commandPick) {
|
44 | this.picker = this.context.commandPick as CommandPicker;
|
45 | }
|
46 | return !!this.picker;
|
47 | }
|
48 |
|
49 | printError(obj: PrintError) {
|
50 | const { pluginPath } = obj;
|
51 | console.log(999999, obj);
|
52 | if (!pluginPath) {
|
53 | if (!this.checkPick()) {
|
54 | this.context.logger.debug('无法找到命令路径');
|
55 | } else {
|
56 | this.context.logger.debug('FefError command pick 初始化成功');
|
57 | }
|
58 | }
|
59 |
|
60 | const docs = this.getDocPath(pluginPath);
|
61 | if (docs) {
|
62 | this.printErrorWithDocs(obj, docs);
|
63 | } else {
|
64 | let { error, msg } = obj;
|
65 | if (!obj.hideError) {
|
66 | msg = `${msg || error}`;
|
67 | this.context.logger.error({ err: error }, msg, chalk.magenta(error));
|
68 | } else {
|
69 |
|
70 | this.context.logger.info(`${msg}`);
|
71 | }
|
72 | }
|
73 | }
|
74 |
|
75 | printErrorWithDocs(obj: PrintError, docs: string) {
|
76 | let { error, msg } = obj;
|
77 | if (!obj.hideError) {
|
78 | msg = `${msg || error}
|
79 | 插件执行发生异常,请查看文档获取更多内容:${chalk.green(docs)}`;
|
80 | this.context.logger.error({ err: error }, msg, chalk.magenta(error));
|
81 | } else {
|
82 |
|
83 | msg = `${msg} 请查看文档获取更多内容:${chalk.green(docs)}`;
|
84 | this.context.logger.info(msg);
|
85 | }
|
86 | }
|
87 |
|
88 | getDocPath(pluginPath?: string) {
|
89 | let docs = '';
|
90 | let configPath = '';
|
91 | let type = COMMAND_TYPE.PLUGIN_TYPE;
|
92 | if (!pluginPath) {
|
93 | if (this.picker != null) {
|
94 | const { path, type: cmdType } = this.picker.getCmdInfo();
|
95 | pluginPath = path;
|
96 | type = cmdType;
|
97 | } else {
|
98 | return docs;
|
99 | }
|
100 | }
|
101 |
|
102 | if (!existsSync(pluginPath)) {
|
103 | return docs;
|
104 | }
|
105 | if (type === COMMAND_TYPE.PLUGIN_TYPE) {
|
106 | configPath = join(pluginPath, this.pluginFile);
|
107 | } else if (type === COMMAND_TYPE.UNIVERSAL_PLUGIN_TYPE) {
|
108 | this.unversalpluginFile.forEach((ext) => {
|
109 | const tmpPath = join(pluginPath as string, ext);
|
110 | if (existsSync(tmpPath)) configPath = tmpPath;
|
111 | });
|
112 | } else if (type === COMMAND_TYPE.NATIVE_TYPE) {
|
113 | return this.defaultDocs;
|
114 | }
|
115 |
|
116 | if (existsSync(configPath)) {
|
117 | const config = this.parseConfig(configPath);
|
118 | this.docsPathList.forEach((docsPath) => {
|
119 | if (docs) return;
|
120 | docs = get(config, docsPath);
|
121 | });
|
122 | } else {
|
123 | this.context.logger.info(`未找到插件配置文件: ${pluginPath}`);
|
124 | }
|
125 |
|
126 | return docs;
|
127 | }
|
128 |
|
129 | parseConfig(filePath: string) {
|
130 | return Config.loadConfigFile(filePath);
|
131 | }
|
132 | }
|