@zhangyu1818/oxlint-config 2.0.0 → 2.1.1

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
@@ -252,7 +252,8 @@ var reactAgentRulesPlugin = resolveReactAgentRulesPluginPath();
252
252
  var reactAgentRules = {
253
253
  "react-agent-rules/effect-empty-deps-only": "error",
254
254
  "react-agent-rules/no-forward-ref": "error",
255
- "react-agent-rules/no-manual-memoization": "error"
255
+ "react-agent-rules/no-manual-memoization": "error",
256
+ "react-agent-rules/no-use-context": "error"
256
257
  };
257
258
 
258
259
  // src/oxlint/presets/react.ts
@@ -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
@@ -690,8 +705,8 @@ function defineOxlintConfig(options = {}) {
690
705
  defaultOxlintPresets.react
691
706
  );
692
707
  const reactAgentRulesPreset = resolveRulePreset(
693
- presets.reactAgentRules,
694
- false
708
+ options.presets?.reactAgentRules,
709
+ reactPreset.enabled
695
710
  );
696
711
  const testPreset = resolveRulePreset(presets.test, defaultOxlintPresets.test);
697
712
  const typeScriptPreset = resolveRulePreset(
@@ -699,6 +714,14 @@ function defineOxlintConfig(options = {}) {
699
714
  defaultOxlintPresets.typescript
700
715
  );
701
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;
702
725
  const plugins = [];
703
726
  const rules = mergeRules(
704
727
  {
@@ -736,6 +759,13 @@ function defineOxlintConfig(options = {}) {
736
759
  appendPlugin(plugins, "node");
737
760
  }
738
761
  const overrides = [];
762
+ if (reactAgentRulesPreset.enabled && reactAgentRulesForSourceFiles) {
763
+ overrides.push({
764
+ files: sourceFiles,
765
+ jsPlugins: [reactAgentRulesPlugin],
766
+ rules: reactAgentRulesForSourceFiles
767
+ });
768
+ }
739
769
  if (javascriptPreset.enabled) {
740
770
  overrides.push({
741
771
  files: scriptFiles,
@@ -841,6 +871,8 @@ function defineOxlintConfig(options = {}) {
841
871
  node: true,
842
872
  ...options.env ?? {}
843
873
  },
874
+ extends: options.extends,
875
+ globals: options.globals,
844
876
  ignorePatterns: ignorePreset.enabled ? dedupe([
845
877
  ...defaultIgnorePatterns,
846
878
  ...ignorePreset.patterns,
@@ -860,6 +892,12 @@ function defineOxlintConfig(options = {}) {
860
892
  if (!config.ignorePatterns || config.ignorePatterns.length === 0) {
861
893
  delete config.ignorePatterns;
862
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
+ }
863
901
  if (!config.overrides || config.overrides.length === 0) {
864
902
  delete config.overrides;
865
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": "2.0.0",
3
+ "version": "2.1.1",
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"
@@ -29,8 +29,8 @@
29
29
  "build": "tsup",
30
30
  "format": "oxfmt -c oxfmt.config.ts .",
31
31
  "format:check": "oxfmt --check -c oxfmt.config.ts .",
32
- "lint": "oxlint",
33
- "lint:fix": "oxlint --fix",
32
+ "lint": "oxlint -c oxlint.config.ts",
33
+ "lint:fix": "oxlint --fix -c oxlint.config.ts",
34
34
  "test": "vitest --run",
35
35
  "test:smoke": "node tests/package-smoke.mjs",
36
36
  "test:watch": "vitest",
@@ -40,21 +40,21 @@
40
40
  "local-pkg": "^1.2.1"
41
41
  },
42
42
  "devDependencies": {
43
- "@types/node": "^25.9.1",
44
- "oxfmt": "^0.51.0",
45
- "oxlint": "^1.66.0",
43
+ "@types/node": "^25.9.3",
44
+ "oxfmt": "^0.54.0",
45
+ "oxlint": "^1.69.0",
46
46
  "oxlint-tsgolint": "^0.23.0",
47
47
  "tsup": "^8.5.1",
48
48
  "typescript": "^6.0.3",
49
- "vitest": "^4.1.7"
49
+ "vitest": "^4.1.8"
50
50
  },
51
51
  "peerDependencies": {
52
- "oxfmt": "^0.51.0",
53
- "oxlint": "^1.66.0",
52
+ "oxfmt": "^0.54.0",
53
+ "oxlint": "^1.69.0",
54
54
  "oxlint-tsgolint": "^0.23.0"
55
55
  },
56
56
  "engines": {
57
- "node": "^20.19.0 || ^22.13.0 || >=24"
57
+ "node": ">=24"
58
58
  },
59
59
  "packageManager": "pnpm@11.2.2"
60
60
  }