@msobiecki/eslint-config 9.10.0 → 9.11.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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [9.11.0](https://github.com/msobiecki/eslint-config/compare/v9.10.0...v9.11.0) (2025-10-21)
2
+
3
+
4
+ ### Features
5
+
6
+ * update eslint 9 ([725c4bb](https://github.com/msobiecki/eslint-config/commit/725c4bbe2857032ac705b25467e3ad6ce377d4b2))
7
+
1
8
  # [9.10.0](https://github.com/msobiecki/eslint-config/compare/v9.9.0...v9.10.0) (2025-10-20)
2
9
 
3
10
 
package/eslint.config.js CHANGED
@@ -20,10 +20,11 @@ import jsxA11yPlugin from "eslint-plugin-jsx-a11y";
20
20
  import importxPlugin from "eslint-plugin-import-x";
21
21
  import storybookPlugin from "eslint-plugin-storybook";
22
22
 
23
- import getTsConfig from "./utils/get-ts-config.js";
23
+ import { getTsConfig, getBaseDirectory } from "./utils/get-ts-config.js";
24
24
 
25
- import baseCustomRules from "./rules/base.js";
25
+ import baseRules from "./rules/base.js";
26
26
  import nodeRules from "./rules/node.js";
27
+ import unicornRules from "./rules/unicorn.js";
27
28
 
28
29
  /**
29
30
  * Base / best-practice preset
@@ -35,7 +36,7 @@ export const basePreset = [
35
36
  rules: {
36
37
  ...eslint.configs.recommended.rules,
37
38
  // Custom best-practice rules
38
- ...baseCustomRules,
39
+ ...baseRules,
39
40
  },
40
41
  },
41
42
  {
@@ -44,7 +45,11 @@ export const basePreset = [
44
45
  languageOptions: {
45
46
  sourceType: "module",
46
47
  parser: tseslint.parser,
47
- parserOptions: { project: getTsConfig(), ecmaFeatures: { jsx: true } },
48
+ parserOptions: {
49
+ project: getTsConfig(),
50
+ tsconfigRootDir: getBaseDirectory(),
51
+ ecmaFeatures: { jsx: true },
52
+ },
48
53
  },
49
54
  plugins: { "@typescript-eslint": tseslint.plugin },
50
55
  rules: {
@@ -79,7 +84,7 @@ export const bestPracticePreset = [
79
84
  ...unicornPlugin.configs?.recommended?.rules,
80
85
  ...prettierPlugin.configs?.recommended?.rules,
81
86
 
82
- "unicorn/no-array-for-each": "off",
87
+ ...unicornRules,
83
88
  },
84
89
  },
85
90
  {
@@ -252,4 +257,9 @@ export const storybookPreset = [
252
257
  },
253
258
  ];
254
259
 
255
- export default [...basePreset, ...bestPracticePreset];
260
+ export default [
261
+ ...basePreset,
262
+ ...bestPracticePreset,
263
+ ...nodePreset,
264
+ ...importPreset,
265
+ ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@msobiecki/eslint-config",
3
- "version": "9.10.0",
3
+ "version": "9.11.0",
4
4
  "private": false,
5
5
  "description": "An ESLint shareable config for JavaScript/TypeScript ecosystem's.",
6
6
  "keywords": [
@@ -0,0 +1,9 @@
1
+ const unicornRules = {
2
+ // allow using forEach instead of requiring map/filter/etc.
3
+ "unicorn/no-array-for-each": "off",
4
+
5
+ // allow using undefined where void 0 could be used
6
+ "unicorn/no-useless-undefined": "off",
7
+ };
8
+
9
+ export default unicornRules;
@@ -2,17 +2,49 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
 
4
4
  /**
5
- * Get tsconfig path if exists
6
- * @returns {string|undefined} tsconfig path or undefined
5
+ * Get the base directory for the project
6
+ * @returns {string} The base directory path
7
+ */
8
+ export function getBaseDirectory() {
9
+ return process.cwd();
10
+ }
11
+
12
+ /**
13
+ * A safe wrapper for fs.existsSync() that only allows
14
+ * checking for files within your current workspace root.
15
+ *
16
+ * This prevents accidental non-literal or user-injected paths,
17
+ * while keeping eslint-plugin-security happy.
18
+ * @param {string} relativePath - The relative path to check
19
+ * @param {string} [baseDirection=process.cwd()] - The base directory to resolve from
20
+ * @returns {boolean} Whether the file exists
7
21
  */
8
- export default function getTsConfig() {
9
- if (fs.existsSync("tsconfig.json")) {
10
- return path.resolve("tsconfig.json");
22
+ export function safeExistsSync(
23
+ relativePath,
24
+ baseDirection = getBaseDirectory(),
25
+ ) {
26
+ const fullPath = path.resolve(baseDirection, relativePath);
27
+ const normalizedBase = path.resolve(baseDirection);
28
+
29
+ if (!fullPath.startsWith(normalizedBase)) {
30
+ throw new Error(
31
+ `Blocked attempt to access outside base directory: ${relativePath}`,
32
+ );
11
33
  }
12
34
 
13
- if (fs.existsSync("../tsconfig.json")) {
14
- return path.resolve("../tsconfig.json");
35
+ return fs.existsSync(fullPath);
36
+ }
37
+
38
+ /**
39
+ * Get tsconfig path if exists
40
+ * @returns {string|undefined} The path to tsconfig.json or undefined if not found
41
+ */
42
+ export function getTsConfig() {
43
+ const baseDirection = getBaseDirectory();
44
+
45
+ if (safeExistsSync("tsconfig.json", baseDirection)) {
46
+ return path.resolve(baseDirection, "tsconfig.json");
15
47
  }
16
48
 
17
- return;
49
+ return undefined;
18
50
  }