@zhangyu1818/oxlint-config 1.0.0 → 2.1.0

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
@@ -65,6 +65,7 @@ react: {
65
65
  - `react-agent-rules/no-manual-memoization`
66
66
  - `react-agent-rules/no-forward-ref`
67
67
  - `react-agent-rules/effect-empty-deps-only`
68
+ - `react-agent-rules/no-use-context`
68
69
 
69
70
  ```ts
70
71
  export default defineConfig({
@@ -104,8 +105,8 @@ Default formatter options:
104
105
  ```json
105
106
  {
106
107
  "scripts": {
107
- "lint": "oxlint",
108
- "lint:fix": "oxlint --fix",
108
+ "lint": "oxlint -c oxlint.config.ts",
109
+ "lint:fix": "oxlint --fix -c oxlint.config.ts",
109
110
  "format": "oxfmt -c oxfmt.config.ts .",
110
111
  "format:check": "oxfmt --check -c oxfmt.config.ts ."
111
112
  }
package/dist/index.d.ts CHANGED
@@ -8,6 +8,8 @@ interface JsonObject {
8
8
  }
9
9
  type RuleConfig = Severity | [Severity, ...JsonValue[]];
10
10
  type Rules = Record<string, RuleConfig>;
11
+ type OxlintGlobalValue = 'off' | 'readable' | 'readonly' | 'writable' | 'writeable' | boolean;
12
+ type OxlintGlobals = Record<string, OxlintGlobalValue>;
11
13
  interface OxlintJsPluginAlias {
12
14
  name: string;
13
15
  specifier: string;
@@ -16,7 +18,9 @@ type OxlintJsPlugin = OxlintJsPluginAlias | string;
16
18
  type OxlintPlugin = 'eslint' | 'import' | 'jest' | 'jsdoc' | 'jsx-a11y' | 'nextjs' | 'node' | 'oxc' | 'promise' | 'react' | 'react-perf' | 'typescript' | 'unicorn' | 'vitest' | 'vue';
17
19
  interface OxlintOverride {
18
20
  env?: Record<string, boolean>;
21
+ excludeFiles?: string[];
19
22
  files: string[];
23
+ globals?: OxlintGlobals;
20
24
  jsPlugins?: OxlintJsPlugin[];
21
25
  plugins?: OxlintPlugin[];
22
26
  rules?: Rules;
@@ -25,6 +29,8 @@ interface OxlintConfig {
25
29
  $schema?: string;
26
30
  categories?: Record<string, Severity>;
27
31
  env?: Record<string, boolean>;
32
+ extends?: string[];
33
+ globals?: OxlintGlobals;
28
34
  ignorePatterns?: string[];
29
35
  jsPlugins?: OxlintJsPlugin[];
30
36
  options?: {
@@ -71,6 +77,8 @@ interface OxlintPresets {
71
77
  interface DefineOxlintConfigOptions {
72
78
  categories?: Record<string, Severity>;
73
79
  env?: Record<string, boolean>;
80
+ extends?: string[];
81
+ globals?: OxlintGlobals;
74
82
  ignorePatterns?: string[];
75
83
  jsPlugins?: OxlintJsPlugin[];
76
84
  overrides?: OxlintOverride[];
@@ -166,4 +174,4 @@ declare const defaultSortImports: SortImportsOptions;
166
174
  declare const defaultOxfmtPresets: Required<OxfmtPresets>;
167
175
  declare function defineOxfmtConfig(options?: DefineOxfmtConfigOptions): OxfmtConfig;
168
176
 
169
- export { type DefineOxfmtConfigOptions, type DefineOxlintConfigOptions, type OxfmtConfig, type OxfmtOverride, type OxfmtPresetConfig, type OxfmtPresets, type OxlintConfig, type OxlintJsPlugin, type OxlintJsPluginAlias, type OxlintOverride, type OxlintPlugin, type OxlintPresetConfig, type OxlintPresets, type ReactOptions, type ReactPresetOptions, type RuleConfig, type Rules, type Severity, type SortImportsOptions, type SortPackageJsonOptions, type TailwindSortOptions, type TypeScriptOptions, defaultIgnorePatterns, defaultOxfmtPresets, defaultOxlintPresets, defaultSortImports, defineConfig, defineOxfmtConfig, defineOxlintConfig };
177
+ export { type DefineOxfmtConfigOptions, type DefineOxlintConfigOptions, type OxfmtConfig, type OxfmtOverride, type OxfmtPresetConfig, type OxfmtPresets, type OxlintConfig, type OxlintGlobalValue, type OxlintGlobals, type OxlintJsPlugin, type OxlintJsPluginAlias, type OxlintOverride, type OxlintPlugin, type OxlintPresetConfig, type OxlintPresets, type ReactOptions, type ReactPresetOptions, type RuleConfig, type Rules, type Severity, type SortImportsOptions, type SortPackageJsonOptions, type TailwindSortOptions, type TypeScriptOptions, defaultIgnorePatterns, defaultOxfmtPresets, defaultOxlintPresets, defaultSortImports, defineConfig, defineOxfmtConfig, defineOxlintConfig };
package/dist/index.js CHANGED
@@ -236,6 +236,26 @@ var nodeRules = {
236
236
  "node/no-path-concat": "error"
237
237
  };
238
238
 
239
+ // src/oxlint/presets/react-agent-rules.ts
240
+ import { existsSync } from "fs";
241
+ import { fileURLToPath } from "url";
242
+ function resolveReactAgentRulesPluginPath() {
243
+ const sourcePluginPath = fileURLToPath(
244
+ new URL("../../react-agent-rules.ts", import.meta.url)
245
+ );
246
+ if (existsSync(sourcePluginPath)) {
247
+ return sourcePluginPath;
248
+ }
249
+ return fileURLToPath(new URL("./react-agent-rules.js", import.meta.url));
250
+ }
251
+ var reactAgentRulesPlugin = resolveReactAgentRulesPluginPath();
252
+ var reactAgentRules = {
253
+ "react-agent-rules/effect-empty-deps-only": "error",
254
+ "react-agent-rules/no-forward-ref": "error",
255
+ "react-agent-rules/no-manual-memoization": "error",
256
+ "react-agent-rules/no-use-context": "error"
257
+ };
258
+
239
259
  // src/oxlint/presets/react.ts
240
260
  import { isPackageExists } from "local-pkg";
241
261
  var jsxA11yRules = {
@@ -356,25 +376,6 @@ function createReactRules(options, nextEnabled) {
356
376
  };
357
377
  }
358
378
 
359
- // src/oxlint/presets/react-agent-rules.ts
360
- import { existsSync } from "fs";
361
- import { fileURLToPath } from "url";
362
- function resolveReactAgentRulesPluginPath() {
363
- const sourcePluginPath = fileURLToPath(
364
- new URL("../../react-agent-rules.ts", import.meta.url)
365
- );
366
- if (existsSync(sourcePluginPath)) {
367
- return sourcePluginPath;
368
- }
369
- return fileURLToPath(new URL("./react-agent-rules.js", import.meta.url));
370
- }
371
- var reactAgentRulesPlugin = resolveReactAgentRulesPluginPath();
372
- var reactAgentRules = {
373
- "react-agent-rules/effect-empty-deps-only": "error",
374
- "react-agent-rules/no-forward-ref": "error",
375
- "react-agent-rules/no-manual-memoization": "error"
376
- };
377
-
378
379
  // src/oxlint/presets/test.ts
379
380
  var vitestRules = {
380
381
  "no-unused-expressions": "off",
@@ -638,6 +639,14 @@ function resolveIgnorePreset(preset, defaultEnabled) {
638
639
  function mergeRules(...entries) {
639
640
  return Object.assign({}, ...entries);
640
641
  }
642
+ function pickRules(rules, predicate) {
643
+ if (!rules) {
644
+ return {};
645
+ }
646
+ return Object.fromEntries(
647
+ Object.entries(rules).filter(([rule]) => predicate(rule))
648
+ );
649
+ }
641
650
  function appendPlugin(plugins, plugin) {
642
651
  if (!plugins.includes(plugin)) {
643
652
  plugins.push(plugin);
@@ -650,6 +659,12 @@ function pruneOverride(override) {
650
659
  if (override.env && Object.keys(override.env).length !== 0) {
651
660
  result.env = override.env;
652
661
  }
662
+ if (override.excludeFiles && override.excludeFiles.length !== 0) {
663
+ result.excludeFiles = override.excludeFiles;
664
+ }
665
+ if (override.globals && Object.keys(override.globals).length !== 0) {
666
+ result.globals = override.globals;
667
+ }
653
668
  if (override.jsPlugins && override.jsPlugins.length !== 0) {
654
669
  result.jsPlugins = override.jsPlugins;
655
670
  }
@@ -659,7 +674,7 @@ function pruneOverride(override) {
659
674
  if (override.rules && Object.keys(override.rules).length !== 0) {
660
675
  result.rules = override.rules;
661
676
  }
662
- return result.rules || result.plugins || result.jsPlugins || result.env ? result : null;
677
+ return result.rules || result.plugins || result.jsPlugins || result.env || result.globals ? result : null;
663
678
  }
664
679
 
665
680
  // src/oxlint/index.ts
@@ -689,13 +704,24 @@ function defineOxlintConfig(options = {}) {
689
704
  presets.react,
690
705
  defaultOxlintPresets.react
691
706
  );
692
- const reactAgentRulesPreset = resolveRulePreset(presets.reactAgentRules, false);
707
+ const reactAgentRulesPreset = resolveRulePreset(
708
+ presets.reactAgentRules,
709
+ false
710
+ );
693
711
  const testPreset = resolveRulePreset(presets.test, defaultOxlintPresets.test);
694
712
  const typeScriptPreset = resolveRulePreset(
695
713
  presets.typescript,
696
714
  defaultOxlintPresets.typescript
697
715
  );
698
716
  const unicornPreset = resolveRulePreset(presets.unicorn, true);
717
+ const reactAgentRulesForSourceFiles = reactAgentRulesPreset.enabled ? mergeRules(
718
+ reactAgentRules,
719
+ reactAgentRulesPreset.rules,
720
+ pickRules(
721
+ options.rules,
722
+ (rule) => rule.startsWith("react-agent-rules/")
723
+ )
724
+ ) : void 0;
699
725
  const plugins = [];
700
726
  const rules = mergeRules(
701
727
  {
@@ -733,6 +759,13 @@ function defineOxlintConfig(options = {}) {
733
759
  appendPlugin(plugins, "node");
734
760
  }
735
761
  const overrides = [];
762
+ if (reactAgentRulesPreset.enabled && reactAgentRulesForSourceFiles) {
763
+ overrides.push({
764
+ files: sourceFiles,
765
+ jsPlugins: [reactAgentRulesPlugin],
766
+ rules: reactAgentRulesForSourceFiles
767
+ });
768
+ }
736
769
  if (javascriptPreset.enabled) {
737
770
  overrides.push({
738
771
  files: scriptFiles,
@@ -838,6 +871,8 @@ function defineOxlintConfig(options = {}) {
838
871
  node: true,
839
872
  ...options.env ?? {}
840
873
  },
874
+ extends: options.extends,
875
+ globals: options.globals,
841
876
  ignorePatterns: ignorePreset.enabled ? dedupe([
842
877
  ...defaultIgnorePatterns,
843
878
  ...ignorePreset.patterns,
@@ -857,6 +892,12 @@ function defineOxlintConfig(options = {}) {
857
892
  if (!config.ignorePatterns || config.ignorePatterns.length === 0) {
858
893
  delete config.ignorePatterns;
859
894
  }
895
+ if (!config.extends || config.extends.length === 0) {
896
+ delete config.extends;
897
+ }
898
+ if (!config.globals || Object.keys(config.globals).length === 0) {
899
+ delete config.globals;
900
+ }
860
901
  if (!config.overrides || config.overrides.length === 0) {
861
902
  delete config.overrides;
862
903
  }
@@ -38,6 +38,14 @@ declare const plugin: {
38
38
  CallExpression(node: CallExpressionNode): void;
39
39
  };
40
40
  };
41
+ 'no-use-context': {
42
+ meta: {
43
+ schema: never[];
44
+ };
45
+ create(context: RuleContext): {
46
+ CallExpression(node: CallExpressionNode): void;
47
+ };
48
+ };
41
49
  };
42
50
  };
43
51
 
@@ -1,10 +1,12 @@
1
1
  // src/react-agent-rules.ts
2
2
  var NO_MANUAL_MEMOIZATION_MESSAGE = "React Compiler automatically optimizes components and values, so manual memoization is not needed.";
3
3
  var NO_FORWARD_REF_MESSAGE = "Starting in React 19, ref is a prop, so forwardRef is no longer needed.";
4
+ var NO_USE_CONTEXT_MESSAGE = "In React 19, use is preferred over useContext for reading context because it is more flexible.";
4
5
  var EFFECT_EMPTY_DEPS_ONLY_MESSAGE = "Effects here must use an empty dependency array. Use them only for mount and unmount logic. For event-driven logic, use useEffectEvent inside the effect. Do not use effects as a watch mechanism.";
5
6
  var manualMemoizationNames = /* @__PURE__ */ new Set(["memo", "useMemo", "useCallback"]);
6
7
  var effectNames = /* @__PURE__ */ new Set(["useEffect", "useLayoutEffect"]);
7
8
  var forwardRefNames = /* @__PURE__ */ new Set(["forwardRef"]);
9
+ var useContextNames = /* @__PURE__ */ new Set(["useContext"]);
8
10
  function isRecord(node) {
9
11
  return typeof node === "object" && node !== null;
10
12
  }
@@ -57,6 +59,23 @@ var noForwardRefRule = {
57
59
  };
58
60
  }
59
61
  };
62
+ var noUseContextRule = {
63
+ meta: {
64
+ schema: []
65
+ },
66
+ create(context) {
67
+ return {
68
+ CallExpression(node) {
69
+ if (isNamedIdentifier(node.callee, useContextNames) || isReactMember(node.callee, useContextNames)) {
70
+ context.report({
71
+ message: NO_USE_CONTEXT_MESSAGE,
72
+ node
73
+ });
74
+ }
75
+ }
76
+ };
77
+ }
78
+ };
60
79
  var effectEmptyDepsOnlyRule = {
61
80
  meta: {
62
81
  schema: []
@@ -85,7 +104,8 @@ var plugin = {
85
104
  rules: {
86
105
  "effect-empty-deps-only": effectEmptyDepsOnlyRule,
87
106
  "no-forward-ref": noForwardRefRule,
88
- "no-manual-memoization": noManualMemoizationRule
107
+ "no-manual-memoization": noManualMemoizationRule,
108
+ "no-use-context": noUseContextRule
89
109
  }
90
110
  };
91
111
  var react_agent_rules_default = plugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhangyu1818/oxlint-config",
3
- "version": "1.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Native Oxlint and Oxfmt config preset package",
5
5
  "keywords": [
6
6
  "oxc",
@@ -11,7 +11,7 @@
11
11
  "license": "MIT",
12
12
  "repository": {
13
13
  "type": "git",
14
- "url": "https://github.com/zhangyu1818/oxlint-config.git"
14
+ "url": "git+https://github.com/zhangyu1818/oxlint-config.git"
15
15
  },
16
16
  "files": [
17
17
  "dist"
@@ -25,35 +25,35 @@
25
25
  "import": "./dist/index.js"
26
26
  }
27
27
  },
28
- "scripts": {
29
- "build": "tsup",
30
- "format": "oxfmt -c oxfmt.config.ts .",
31
- "format:check": "oxfmt --check -c oxfmt.config.ts .",
32
- "lint": "oxlint",
33
- "lint:fix": "oxlint --fix",
34
- "test": "vitest --run",
35
- "test:watch": "vitest",
36
- "tsc:check": "tsc"
37
- },
38
28
  "dependencies": {
39
- "local-pkg": "^1.1.2"
29
+ "local-pkg": "^1.2.1"
40
30
  },
41
31
  "devDependencies": {
42
- "@types/node": "^25.5.0",
43
- "oxfmt": "^0.45.0",
44
- "oxlint": "^1.60.0",
45
- "oxlint-tsgolint": "^0.21.1",
32
+ "@types/node": "^25.9.3",
33
+ "oxfmt": "^0.54.0",
34
+ "oxlint": "^1.69.0",
35
+ "oxlint-tsgolint": "^0.23.0",
46
36
  "tsup": "^8.5.1",
47
- "typescript": "^5.9.3",
48
- "vitest": "^4.1.0"
37
+ "typescript": "^6.0.3",
38
+ "vitest": "^4.1.8"
49
39
  },
50
40
  "peerDependencies": {
51
- "oxfmt": "^0.45.0",
52
- "oxlint": "^1.60.0",
53
- "oxlint-tsgolint": "^0.21.1"
41
+ "oxfmt": "^0.54.0",
42
+ "oxlint": "^1.69.0",
43
+ "oxlint-tsgolint": "^0.23.0"
54
44
  },
55
45
  "engines": {
56
- "node": "^20.19.0 || ^22.13.0 || >=24"
46
+ "node": ">=24"
57
47
  },
58
- "packageManager": "pnpm@10.32.1"
59
- }
48
+ "scripts": {
49
+ "build": "tsup",
50
+ "format": "oxfmt -c oxfmt.config.ts .",
51
+ "format:check": "oxfmt --check -c oxfmt.config.ts .",
52
+ "lint": "oxlint -c oxlint.config.ts",
53
+ "lint:fix": "oxlint --fix -c oxlint.config.ts",
54
+ "test": "vitest --run",
55
+ "test:smoke": "node tests/package-smoke.mjs",
56
+ "test:watch": "vitest",
57
+ "tsc:check": "tsc"
58
+ }
59
+ }