rhine-lint 1.4.3 → 1.5.2

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/README.md CHANGED
@@ -111,6 +111,10 @@ export default {
111
111
 
112
112
  // ESLint 专项配置
113
113
  eslint: {
114
+ // 是否启用 ESLint (默认为 true)
115
+ // 设为 false 可禁用 ESLint 检查
116
+ enable: true,
117
+
114
118
  // 启用/禁用特定范围的规则
115
119
  scope: {
116
120
  frontend: true, // 开启前端规则 (React 等)
@@ -133,6 +137,10 @@ export default {
133
137
 
134
138
  // Prettier 专项配置
135
139
  prettier: {
140
+ // 是否启用 Prettier (默认为 true)
141
+ // 设为 false 可禁用 Prettier 格式检查
142
+ enable: true,
143
+
136
144
  config: {
137
145
  printWidth: 100,
138
146
  semi: true,
@@ -154,6 +162,9 @@ CLI 参数优先级高于配置文件:
154
162
  - `--ignore-file <path>`: 指定类似 `.gitignore` 的忽略文件 (支持多次使用, e.g. `--ignore-file .gitignore --ignore-file .eslintignore`)。
155
163
  - `--ignore <pattern>`: 添加忽略模式 (支持多次使用, e.g. `--ignore dist --ignore coverage`)。
156
164
  - `--no-ignore`: 强制禁用所有忽略规则 (包括 ignoreFiles 和 ignores)。
165
+ - `--disable-eslint`: 禁用 ESLint 检查 (覆盖配置文件中的 `eslint.enable`)。
166
+ - `--disable-prettier`: 禁用 Prettier 格式检查 (覆盖配置文件中的 `prettier.enable`)。
167
+ - `--no-time`: 禁用各阶段耗时信息显示(默认启用)。
157
168
  - `--debug`: 打印调试信息(包括生成的配置、忽略列表等)。
158
169
  - `--cache-dir <dir>`: 指定缓存目录(默认使用 `node_modules/.cache/rhine-lint`)。
159
170
 
@@ -337,6 +348,9 @@ cli
337
348
  .option("--ignore [pattern]", "Add ignore pattern (can be used multiple times)")
338
349
  .option("--no-ignore", "Disable all ignore rules")
339
350
  .option("--cache-dir <dir>", "Custom cache directory")
351
+ .option("--no-time", "Disable elapsed time display")
352
+ .option("--disable-eslint", "Disable ESLint linting")
353
+ .option("--disable-prettier", "Disable Prettier formatting check")
340
354
  .option("--debug", "Enable debug mode")
341
355
  ```
342
356
 
@@ -534,16 +548,21 @@ export type Config = {
534
548
  type?: 'js' | 'ts' | 'frontend' | 'react' | 'nextjs',
535
549
  cacheDir?: string,
536
550
  fix?: boolean,
537
- projectTypeCheck?: boolean, // 启用项目级类型检查 (default: true)
538
- tsconfig?: string, // tsconfig 文件路径 (default: './tsconfig.json')
539
- ignore?: string[], // 额外的忽略模式
551
+ time?: boolean, // 显示各阶段耗时 (default: true)
552
+ projectTypeCheck?: boolean, // 启用项目级类型检查 (default: true)
553
+ tsconfig?: string, // tsconfig 文件路径 (default: './tsconfig.json')
554
+ ignoreFiles?: string[], // gitignore 风格的忽略文件列表 (default: ['./.gitignore'])
555
+ ignores?: string[], // 忽略模式列表 (default: ['package-lock.json', ...])
556
+ ignore?: string[], // [deprecated] 使用 ignores 代替
540
557
  eslint?: {
541
- config?: [...], // ESLint Flat Config 数组
542
- overlay?: boolean, // 覆盖模式
558
+ enable?: boolean, // 是否启用 ESLint (default: true)
559
+ config?: [...], // ESLint Flat Config 数组
560
+ overlay?: boolean, // 覆盖模式 (true: 完全覆盖内置配置)
543
561
  },
544
562
  prettier?: {
545
- config?: {...}, // Prettier 配置对象
546
- overlay?: boolean,
563
+ enable?: boolean, // 是否启用 Prettier (default: true)
564
+ config?: {...}, // Prettier 配置对象
565
+ overlay?: boolean, // 覆盖模式 (true: 完全覆盖内置配置)
547
566
  }
548
567
  }
549
568
  ```
package/dist/cli.js CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'module';
3
- // import cac from "cac";
4
3
  import path from "node:path";
5
4
  import { loadUserConfig, generateTempConfig, cleanup } from "./core/config.js";
6
5
  import { runEslint, runPrettier } from "./core/runner.js";
@@ -21,15 +20,17 @@ cli
21
20
  .option("--ignore [pattern]", "Add ignore pattern (can be used multiple times)")
22
21
  .option("--no-ignore", "Disable all ignore rules (including .gitignore)")
23
22
  .option("--cache-dir <dir>", "Custom temporary cache directory")
24
- .option("--time", "Show elapsed time for each phase")
23
+ .option("--no-time", "Disable elapsed time display for each phase")
24
+ .option("--disable-eslint", "Disable ESLint linting")
25
+ .option("--disable-prettier", "Disable Prettier formatting check")
25
26
  .option("--debug", "Enable debug mode")
26
27
  .action(async (files, options) => {
27
28
  const cwd = process.cwd();
28
29
  // If files is empty, default to "."
29
30
  const targetFiles = files.length > 0 ? files : ["."];
30
31
  let usedCachePath;
31
- // 计时功能:从 CLI 选项或配置文件获取
32
- let showTime = options.time ?? false;
32
+ // 计时功能:默认启用,可通过 --no-time 或配置文件禁用
33
+ let showTime = options.time !== false;
33
34
  const startTotal = Date.now();
34
35
  let startPhase = startTotal;
35
36
  try {
@@ -75,34 +76,55 @@ cli
75
76
  startPhase = Date.now();
76
77
  }
77
78
  console.log();
79
+ // 确定是否启用 ESLint 和 Prettier(CLI 选项优先于配置文件)
80
+ const enableEslint = options.disableEslint ? false : (userConfigResult.config.eslint?.enable ?? true);
81
+ const enablePrettier = options.disablePrettier ? false : (userConfigResult.config.prettier?.enable ?? true);
82
+ let eslintResult = null;
83
+ let prettierResult = null;
78
84
  // 3. Run ESLint
79
- const eslintResult = await runEslint(cwd, temps.eslintPath, options.fix, targetFiles);
80
- // 计时:第二阶段(ESLint)
81
- if (showTime) {
82
- logTime("ESLint", Date.now() - startPhase);
83
- startPhase = Date.now();
85
+ if (enableEslint) {
86
+ eslintResult = await runEslint(cwd, temps.eslintPath, options.fix ?? false, targetFiles);
87
+ // 计时:第二阶段(ESLint)
88
+ if (showTime) {
89
+ logTime("ESLint", Date.now() - startPhase);
90
+ startPhase = Date.now();
91
+ }
92
+ console.log();
93
+ }
94
+ else {
95
+ logInfo("ESLint: Disabled");
96
+ console.log();
84
97
  }
85
- console.log();
86
98
  // 4. Run Prettier
87
- const prettierResult = await runPrettier(cwd, temps.prettierPath, options.fix, targetFiles);
88
- // 计时:第三阶段(Prettier)
89
- if (showTime) {
90
- logTime("Prettier", Date.now() - startPhase);
99
+ if (enablePrettier) {
100
+ prettierResult = await runPrettier(cwd, temps.prettierPath, options.fix ?? false, targetFiles);
101
+ // 计时:第三阶段(Prettier)
102
+ if (showTime) {
103
+ logTime("Prettier", Date.now() - startPhase);
104
+ }
105
+ console.log();
106
+ }
107
+ else {
108
+ logInfo("Prettier: Disabled");
109
+ console.log();
91
110
  }
92
- console.log();
93
111
  if (eslintResult || prettierResult) {
94
112
  logError("Linting completed with issues:");
95
- if (eslintResult) {
96
- logError(`ESLint: ${eslintResult}`);
97
- }
98
- else {
99
- logSuccess(`ESLint: No issues found`);
100
- }
101
- if (prettierResult) {
102
- logError(`Prettier: ${prettierResult}`);
113
+ if (enableEslint) {
114
+ if (eslintResult) {
115
+ logError(`ESLint: ${eslintResult}`);
116
+ }
117
+ else {
118
+ logSuccess(`ESLint: No issues found`);
119
+ }
103
120
  }
104
- else {
105
- logSuccess(`Prettier: No issues found`);
121
+ if (enablePrettier) {
122
+ if (prettierResult) {
123
+ logError(`Prettier: ${prettierResult}`);
124
+ }
125
+ else {
126
+ logSuccess(`Prettier: No issues found`);
127
+ }
106
128
  }
107
129
  process.exit(1);
108
130
  }
package/dist/config.d.ts CHANGED
@@ -1,11 +1,35 @@
1
+ /**
2
+ * Rhine Lint configuration options.
3
+ * All options are optional with sensible defaults.
4
+ * Priority: CLI arguments > Config file > Default values
5
+ */
1
6
  export type Config = {
7
+ /**
8
+ * Project type level that determines which linting rules to enable.
9
+ * Each level includes all rules from previous levels:
10
+ * - `'js'`: JavaScript only (no type checking)
11
+ * - `'ts'`: TypeScript with type-aware rules
12
+ * - `'frontend'` / `'react'`: TypeScript + React/JSX/Hooks rules
13
+ * - `'nextjs'`: TypeScript + React + Next.js specific rules
14
+ * @default 'frontend'
15
+ */
2
16
  type?: 'js' | 'ts' | 'frontend' | 'react' | 'nextjs';
17
+ /**
18
+ * Directory for storing generated virtual config files and cache metadata.
19
+ * Can be absolute or relative to the project root.
20
+ * @default 'node_modules/.cache/rhine-lint' (if node_modules exists) or '.cache/rhine-lint'
21
+ */
3
22
  cacheDir?: string;
23
+ /**
24
+ * Automatically fix linting errors and formatting issues.
25
+ * When enabled, ESLint will apply auto-fixes and Prettier will rewrite files.
26
+ * @default false
27
+ */
4
28
  fix?: boolean;
5
29
  /**
6
30
  * Enable timing output for each phase.
7
31
  * Shows elapsed time for: preparation, ESLint, and Prettier phases.
8
- * @default false
32
+ * @default true
9
33
  */
10
34
  time?: boolean;
11
35
  /**
@@ -43,13 +67,71 @@ export type Config = {
43
67
  * @example ['temp', 'generated', '*.test.ts']
44
68
  */
45
69
  ignore?: string[];
70
+ /**
71
+ * ESLint configuration options.
72
+ */
46
73
  eslint?: {
74
+ /**
75
+ * Enable ESLint linting.
76
+ * Set to `false` to skip ESLint entirely (only run Prettier).
77
+ * @default true
78
+ */
79
+ enable?: boolean;
80
+ /**
81
+ * ESLint Flat Config array to extend or override default rules.
82
+ * These configurations are merged with Rhine Lint's built-in rules.
83
+ * @see https://eslint.org/docs/latest/use/configure/configuration-files
84
+ * @example
85
+ * ```ts
86
+ * config: [
87
+ * {
88
+ * rules: {
89
+ * 'no-console': 'warn',
90
+ * '@typescript-eslint/no-unused-vars': 'off'
91
+ * }
92
+ * }
93
+ * ]
94
+ * ```
95
+ */
47
96
  config?: [
48
97
  ];
98
+ /**
99
+ * Overlay mode for ESLint configuration.
100
+ * - `true`: User config completely replaces Rhine Lint's default rules
101
+ * - `false`: User config is merged with Rhine Lint's default rules
102
+ * @default false
103
+ */
49
104
  overlay?: boolean;
50
105
  };
106
+ /**
107
+ * Prettier configuration options.
108
+ */
51
109
  prettier?: {
110
+ /**
111
+ * Enable Prettier formatting check.
112
+ * Set to `false` to skip Prettier entirely (only run ESLint).
113
+ * @default true
114
+ */
115
+ enable?: boolean;
116
+ /**
117
+ * Prettier options to extend or override default formatting rules.
118
+ * @see https://prettier.io/docs/en/options.html
119
+ * @example
120
+ * ```ts
121
+ * config: {
122
+ * semi: true,
123
+ * singleQuote: false,
124
+ * printWidth: 80
125
+ * }
126
+ * ```
127
+ */
52
128
  config?: {};
129
+ /**
130
+ * Overlay mode for Prettier configuration.
131
+ * - `true`: User config completely replaces Rhine Lint's default options
132
+ * - `false`: User config is merged with Rhine Lint's default options
133
+ * @default false
134
+ */
53
135
  overlay?: boolean;
54
136
  };
55
137
  };
@@ -263,7 +263,8 @@ export async function generateTempConfig(cwd, userConfigResult, cliLevel, cliCac
263
263
  const defuUrl = pathToFileURL(require.resolve("defu")).href;
264
264
  const jitiUrl = pathToFileURL(require.resolve("jiti")).href;
265
265
  let finalUserConfigUrl = userConfigUrl;
266
- if (userConfigResult.path && (userConfigResult.path.endsWith('.ts') || userConfigResult.path.endsWith('.mts') || userConfigResult.path.endsWith('.cts'))) {
266
+ const tsExtensions = ['.ts', '.mts', '.cts'];
267
+ if (userConfigResult.path && tsExtensions.some(ext => userConfigResult.path.endsWith(ext))) {
267
268
  try {
268
269
  const ts = await import('typescript');
269
270
  const fileContent = await fs.readFile(userConfigResult.path, 'utf-8');
@@ -16,7 +16,7 @@ function resolveBin(pkgName, binPathRelative) {
16
16
  return require.resolve(`${pkgName}/${binPathRelative}`);
17
17
  }
18
18
  catch (e) {
19
- if (e.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED' && e.code !== 'MODULE_NOT_FOUND') {
19
+ if (e instanceof Error && e.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED' && e.code !== 'MODULE_NOT_FOUND') {
20
20
  logger.debug(`Resolve error for ${pkgName}/${binPathRelative}:`, e);
21
21
  }
22
22
  }
@@ -114,7 +114,7 @@ export async function runEslint(cwd, configPath, fix, files = ["."]) {
114
114
  }
115
115
  catch (e) {
116
116
  logError("Failed to run ESLint", e);
117
- return e.message || "Unknown error";
117
+ return e instanceof Error ? e.message : "Unknown error";
118
118
  }
119
119
  }
120
120
  export async function runPrettier(cwd, configPath, fix, files = ["."]) {
@@ -153,6 +153,6 @@ export async function runPrettier(cwd, configPath, fix, files = ["."]) {
153
153
  }
154
154
  catch (e) {
155
155
  logError("Failed to run Prettier", e);
156
- return e.message || "Unknown error";
156
+ return e instanceof Error ? e.message : "Unknown error";
157
157
  }
158
158
  }
@@ -1,10 +1,6 @@
1
1
  import { createConsola } from "consola";
2
2
  import { colors } from "consola/utils";
3
3
  const { cyan, red, green, yellow, gray } = colors;
4
- // Custom logger to satisfy "RL" prefix requirement
5
- const rLine = (colorFn, type, msg) => {
6
- console.log(`${colorFn("RL")} ${msg}`);
7
- };
8
4
  export const logger = createConsola({
9
5
  level: 3,
10
6
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rhine-lint",
3
- "version": "1.4.3",
3
+ "version": "1.5.2",
4
4
  "module": "./dist/index.js",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,7 +18,7 @@
18
18
  "react",
19
19
  "opinionated"
20
20
  ],
21
- "author": "RhineAI <hran@rhine.ai>",
21
+ "author": "RhineAI <rhineai@163.com>",
22
22
  "license": "MIT",
23
23
  "repository": {
24
24
  "type": "git",