diff --git a/.gitignore b/.gitignore index abe0d77..575025e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ dist .dumi server pnpm-lock.yaml +.idea diff --git a/README.md b/README.md index 3673304..23a730c 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ npm run build:all 已有 `examples/webtools` 进行调试 ```sh -cd examples/webtools +cd examples/web-tools npm run doctor:webtools ``` @@ -22,10 +22,10 @@ npm run doctor:webtools 因为 monorepo 的缘故 无需手动 `link`,修改源码后 `examples` 中即可查看效果 ```sh -cd packages/doctor-webtools +cd packages/web-tools npm run dev -npm run doctor:webtools //记得回到 examples/webtools 中 +npm run doctor:webtools //记得回到 examples/web-tools 中 ``` #### 文档贡献指南: diff --git a/examples/eslint/.eslintrc.json b/examples/eslint/.eslintrc.json new file mode 100644 index 0000000..535270a --- /dev/null +++ b/examples/eslint/.eslintrc.json @@ -0,0 +1,8 @@ +{ + "extends": "standard-with-typescript", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "rules": {} +} diff --git a/examples/eslint/package.json b/examples/eslint/package.json new file mode 100644 index 0000000..7c38ec0 --- /dev/null +++ b/examples/eslint/package.json @@ -0,0 +1,18 @@ +{ + "name": "eslint-example", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "doctor:eslint": "doctor eslint", + "test": "npm run doctor:eslint" + }, + "dependencies": { + "@doctors/core": "workspace:^", + "@doctors/eslint": "workspace:^", + "eslint": "^8.43.0" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/packages/eslint/.fatherrc.ts b/packages/eslint/.fatherrc.ts new file mode 100644 index 0000000..8d95240 --- /dev/null +++ b/packages/eslint/.fatherrc.ts @@ -0,0 +1,5 @@ +import { defineConfig } from "father"; + +export default defineConfig({ + extends: "../../.fatherrc.base", +}); diff --git a/packages/eslint/.npmrc b/packages/eslint/.npmrc new file mode 100644 index 0000000..38f11c6 --- /dev/null +++ b/packages/eslint/.npmrc @@ -0,0 +1 @@ +registry=https://registry.npmjs.org diff --git a/packages/eslint/package.json b/packages/eslint/package.json new file mode 100644 index 0000000..2ec85f2 --- /dev/null +++ b/packages/eslint/package.json @@ -0,0 +1,34 @@ +{ + "name": "@doctors/eslint", + "version": "0.0.3", + "description": "", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "dev": "father dev", + "build": "father build", + "build:deps": "father prebundle", + "prepublishOnly": "father doctor && npm run build" + }, + "repository": "https://github.com/BoyYangzai/doctor", + "keywords": [], + "authors": [ + "洋" + ], + "license": "MIT", + "files": [ + "./dist", + "./bin" + ], + "publishConfig": { + "access": "public" + }, + "peerDependencies": { + "@doctors/core": "workspace:^" + }, + "dependencies": { + "@doctors/utils": "workspace:^", + "@umijs/core": "^4.0.71", + "@umijs/utils": "^4.0.71" + } +} diff --git a/packages/eslint/src/commands/eslint.ts b/packages/eslint/src/commands/eslint.ts new file mode 100644 index 0000000..878eff1 --- /dev/null +++ b/packages/eslint/src/commands/eslint.ts @@ -0,0 +1,22 @@ +import { generatePreset } from "@doctors/core"; +import { IApi } from "../type"; +import { ConfigSchema } from "../type"; +import { Nullify } from "@doctors/core"; +import { getConfigFile } from "../features/checkConfigured"; +import { PRESET_NAME } from "../constants"; + +const schema: Nullify = { + eslint: {}, +}; + +export default (api: IApi) => { + const meta = { + eslintConfig: getConfigFile(api), // 从 getConfigFile 获取 + }; + generatePreset({ + api, + command: PRESET_NAME, + schema, + meta, + }); +}; diff --git a/packages/eslint/src/constants.ts b/packages/eslint/src/constants.ts new file mode 100644 index 0000000..0c0db87 --- /dev/null +++ b/packages/eslint/src/constants.ts @@ -0,0 +1 @@ +export const PRESET_NAME = "eslint"; diff --git a/packages/eslint/src/defineConfig.ts b/packages/eslint/src/defineConfig.ts new file mode 100644 index 0000000..e50e57a --- /dev/null +++ b/packages/eslint/src/defineConfig.ts @@ -0,0 +1,6 @@ +import { ConfigSchema } from "./type"; + +const defineConfig = (config: ConfigSchema) => { + return config; +}; +export default defineConfig; diff --git a/packages/eslint/src/features/checkConfigured.ts b/packages/eslint/src/features/checkConfigured.ts new file mode 100644 index 0000000..862e146 --- /dev/null +++ b/packages/eslint/src/features/checkConfigured.ts @@ -0,0 +1,53 @@ +import type { IApi } from "../type"; +import { DoctorLevel } from "@doctors/core"; + +const fs = require("fs"); +const path = require("path"); +export default (api: IApi) => { + // 解构 meta + api.addDoctorEslintCheck((meta) => { + const { eslintConfig } = meta; + let isEsLintOk: boolean = true; + const prerequisites = ["env", "extends", "parserOptions", "rules"]; + const configKeys = Object.keys(eslintConfig); + prerequisites.forEach((item) => { + if (!configKeys.includes(item)) { + isEsLintOk = false; + } + }); + const doctorLevel = isEsLintOk ? DoctorLevel.SUCCESS : DoctorLevel.WARN; + return isEsLintOk + ? { + label: "ESLint Check", + description: "ESLint prerequisites have been configured", + doctorLevel, + } + : { + label: "ESLint Check", + description: "ESLint prerequisites have not been configured", + doctorLevel, + }; + }); +}; +/** + * @description:获取eslint配置 + * @return {*} + * @param api + */ +export function getConfigFile(api: IApi) { + const cwd = api.service.paths.cwd; + let config = ""; + let files = fs.readdirSync(cwd); + for (let i = 0; i < files.length; i++) { + if (files[i].includes("eslintrc")) { + const filedir = path.join(cwd, files[i]); + const file = fs.statSync(filedir); + if (file.isFile()) { + //判断是否为文件 + config = fs.readFileSync(filedir, "utf-8"); + return JSON.parse(config); + } + } + } + //也可能在package.json中 +} diff --git a/packages/eslint/src/features/index.ts b/packages/eslint/src/features/index.ts new file mode 100644 index 0000000..9884d84 --- /dev/null +++ b/packages/eslint/src/features/index.ts @@ -0,0 +1 @@ +export default [require.resolve("./checkConfigured")]; diff --git a/packages/eslint/src/index.ts b/packages/eslint/src/index.ts new file mode 100644 index 0000000..817c9ae --- /dev/null +++ b/packages/eslint/src/index.ts @@ -0,0 +1,23 @@ +import features from "./features"; +import { IApi } from "./type"; +import { PRESET_NAME } from "./constants"; + +// 为用户导出需要的 类型 和 工具函数 +export * from "./type"; +export { default as defineConfig } from "./defineConfig"; + +export default (api: IApi) => { + // key 用来识别插件 否则会使用默认的小驼峰包名 容易和其他插件重复 + api.describe({ + key: `doctor-preset-${PRESET_NAME}`, + }); + + return { + plugins: [ + //commands + require.resolve("./commands/eslint"), + //features + ...features, + ], + }; +}; diff --git a/packages/eslint/src/type.ts b/packages/eslint/src/type.ts new file mode 100644 index 0000000..93e7554 --- /dev/null +++ b/packages/eslint/src/type.ts @@ -0,0 +1,24 @@ +import type { IApi as DoctorApi, DoctorMeta, DoctorLevel } from "@doctors/core"; + +// 校验配置文件以及类型提示的 Schema 列表 +/** + * 用每一个 Preset 来单独维护 Schema 以便获得更全面的类型提示 + */ +export interface ConfigSchema { + eslint: {}; +} + +// 元数据 +interface Meta { + eslintConfig: object; +} + +export type IApi = DoctorApi & { + addDoctorEslintCheckBefore: (fn: () => void) => void; + + addDoctorEslintCheck: { + (fn: (meta: Meta) => DoctorMeta | undefined): void; + }; + + addDoctorEslintCheckEnd: (fn: () => void) => void; +};