Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add checkVSCodePlugins webtools #7

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions examples/web-tools/.doctor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,14 @@ import { defineConfig } from "@doctors/web-tools";
export default defineConfig({
webTools: {
nodeVersion: DoctorLevel.ERROR,
vscode: {
morePlugins: [
{
name: "Vue.volar",
desc: "成功时描述",
version: "1.0",
},
],
},
},
});
1 change: 1 addition & 0 deletions packages/web-tools/src/commands/web-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { PRESET_NAME } from "../constants";
const schema: Nullify<ConfigSchema> = {
webTools: {
nodeVersion: null,
vscode: null,
},
};

Expand Down
2 changes: 1 addition & 1 deletion packages/web-tools/src/features/checkNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default (api: IApi) => {
api.addDoctorWebToolsCheck(() => {
const nodeVersion = parseInt(process.version.slice(1));

const ruleLevel = (api.userConfig.tools?.nodeVersion ||
const ruleLevel = (api.userConfig.webTools?.nodeVersion ||
DoctorLevel.WARN) as DoctorLevel;

if (ruleLevel === DoctorLevel.OFF) return;
Expand Down
152 changes: 152 additions & 0 deletions packages/web-tools/src/features/checkVSCodePlugins.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { DoctorLevel } from "@doctors/core";
import { IApi } from "../type";
import { exec } from "child_process";
import { chalkByDoctorLevel } from "@doctors/utils";

/* VSCode plugins type */
export type VSCodePluginsConfig = (
| string
| { name: string; desc: string; version?: string }
)[];

/* Constants */
const FEATURE_NAME = "VSCode Plugins";
const BASIC_VSCODE_PLUGINS: VSCodePluginsConfig = [];
const OUTPUT_DEMARCATORS = "\n\t- ";

/**
* Execute command
*/
function execCommand(command: string): Promise<string> {
return new Promise((resolve, reject) => {
const child = exec(command, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
resolve(stdout.trim());
}
});

child.on("close", () => {
child.kill();
});
});
}

async function filterPluginsConfig(
plugins: VSCodePluginsConfig
): Promise<[string[], string[]]> {
const failedRecords: string[] = [];
const successRecords: string[] = [];

try {
const localPluginsMap = await getLocalPlugins();
plugins.forEach((item) => {
if (typeof item === "string" && !localPluginsMap.has(item)) {
const name = item;
failedRecords.push(`${name} plugin: You should install ${name} plugin`);
} else if (typeof item === "object" && item !== null) {
const { name, desc, version: targetVersion } = item;
if (!localPluginsMap.has(name)) {
failedRecords.push(
`${name} plugin: You should install ${name}@${targetVersion} plugin`
);
} else {
// check version
if (targetVersion != null) {
const localVersion = localPluginsMap.get(name) as string;
if (compareVersion(localVersion, targetVersion) < 0) {
failedRecords.push(
`${name} plugin: You should update the ${name} plugin to version v${targetVersion} and above ${chalkByDoctorLevel(
DoctorLevel.ERROR,
"Now: v" + localVersion
)}`
);
}
}
successRecords.push(`Installed ${name} plugin: ${desc}`);
}
}
});
} catch (error) {
console.error(error);
}

return [failedRecords, successRecords];
}

/**
* Get local VSCode plugins
*/
async function getLocalPlugins() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

提取 通用 utils 到 @dodctors/utils 这个包

const stdout =
(await execCommand("code --list-extensions --show-versions")) || "";
const pluginMap = stdout.split("\n").reduce((map, item) => {
const [name, version] = item.split("@");
map.set(name, version);
return map;
}, new Map<string, string>());
return pluginMap;
}

/**
* Compare version numbers
*/
function compareVersion(a: string, b: string) {
const versionReg = /^\d+?(\.\d+){0,2}$/;
if (!versionReg.test(a) || !versionReg.test(b)) {
throw TypeError(
`There is an error in the version resolution of the VSCode plugin ${
versionReg.test(a) ? b : a
}, please make sure you have configured the version number in the correct format`
);
}
let aV = a.split(".").map(Number),
bV = b.split(".").map(Number);

for (let i = 0; i < 3; i++) {
if (aV[i] == null || bV[i] == null) {
if (aV[i] == null) return -1;
else return 1;
}
if (aV[i] > bV[i]) {
return 1;
} else if (aV[i] < bV[i]) {
return -1;
}
}
return 0;
}

export default (api: IApi) => {
api.addDoctorWebToolsCheck(async () => {
const vscodePlugins: VSCodePluginsConfig = [
...BASIC_VSCODE_PLUGINS,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以写几个最通用的先
Auto Rename Tag Chinese (Simplified) (简体中文) Language Pack for Visual Studi. Code Spell Checker Error Lens Live Server One Dark Pro Prettier - Code formatter
description 按照功能随意发挥

...(api.userConfig.webTools?.vscode?.morePlugins || []),
];

const [failedRecords, successRecords] = await filterPluginsConfig(
vscodePlugins
);

if (failedRecords.length === 0) {
let description =
successRecords.length === 0
? "You have installed all the required VSCode plugins"
: `${OUTPUT_DEMARCATORS}${successRecords.join(OUTPUT_DEMARCATORS)}\n`;
return {
label: FEATURE_NAME,
description,
doctorLevel: DoctorLevel.SUCCESS,
};
} else {
return {
label: FEATURE_NAME,
description: `${OUTPUT_DEMARCATORS}${failedRecords.join(
OUTPUT_DEMARCATORS
)}\n`,
doctorLevel: DoctorLevel.ERROR,
};
}
});
};
1 change: 1 addition & 0 deletions packages/web-tools/src/features/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export default [
require.resolve("./checkNode"),
require.resolve("./checkChrome"),
require.resolve("./checkVSCodePlugins"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

按照到类型放在一起比较合适一点
这样通过 api.addDoctorWebToolsCheckBefore 可以做类别区分
such as:

api.addDoctorWebToolsCheckBefore(()=>{
    console.log('以下是对常用 VsCodePlugin 进行检测') // 当然 ui 可以随意diy
})

require.resolve("./checkDefaultBrowser"),
];
6 changes: 6 additions & 0 deletions packages/web-tools/src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ import type { Awaitable } from "@doctors/utils";
export interface ConfigSchema {
webTools: {
nodeVersion: DoctorLevel;
vscode: {
morePlugins: (
| string
| { name: string; desc: string; version?: string }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里可以抽出来一个

type ExtraPlugin = 

)[];
};
};
}

Expand Down