Skip to content

feat!: Support basePath property in config objects #223

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jun 25, 2025
Merged

feat!: Support basePath property in config objects #223

merged 14 commits into from
Jun 25, 2025

Conversation

mdjermanovic
Copy link
Member

@mdjermanovic mdjermanovic commented Jun 8, 2025

Prerequisites checklist

What is the purpose of this pull request?

Implements https://github.com/eslint/rfcs/tree/main/designs/2025-base-path-in-config-objects in @eslint/config-array and @eslint/config-helpers.

What changes did you make? (Give an overview)

This PR adds support for basePath property in config objects.

Marked as a breaking change for this package for two reasons:

  1. basePath can no longer be used as a custom property.
  2. get ignores now returns an array of objects instead of an array of ignore patterns.

Related Issues

eslint/rfcs#131

eslint/eslint#18948

Is there anything you'd like reviewers to focus on?

WIP. The proof of concept worked well with ESLint, as it always sends filenames as absolute paths. Accepting relative paths makes this a bit more complicated.

@nzakas nzakas moved this from Needs Triage to Implementing in Triage Jun 18, 2025
@mdjermanovic mdjermanovic marked this pull request as ready for review June 18, 2025 18:10
nzakas
nzakas previously approved these changes Jun 19, 2025
Copy link
Member

@nzakas nzakas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM. Left one note about a slight refactor.

Would like @fasttime to review before merging.

@@ -307,6 +317,17 @@ function normalizeConfigPatterns(config) {

const newConfig = { ...config };

if (typeof config.basePath === "string") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we have this same check on line 297? Maybe an opportunity to store in a variable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in 92a98b1

nzakas
nzakas previously approved these changes Jun 20, 2025
Copy link
Member

@fasttime fasttime left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of suggestions, otherwise LGTM.

Comment on lines +323 to +330
if (path.isAbsolute(config.basePath)) {
newConfig.basePath = path.toNamespacedPath(config.basePath);
} else {
newConfig.basePath = path.resolve(
namespacedBasePath,
config.basePath,
);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be simplified to remove the check with path.isAbsolute, which path.resolve should already include. From https://nodejs.org/api/path.html#pathresolvepaths:

The given sequence of paths is processed from right to left, with each subsequent path prepended until an absolute path is constructed. For instance, given the sequence of path segments: /foo, /bar, baz, calling path.resolve('/foo', '/bar', 'baz') would return /bar/baz because 'baz' is not an absolute path but '/bar' + '/' + 'baz' is.

Suggested change
if (path.isAbsolute(config.basePath)) {
newConfig.basePath = path.toNamespacedPath(config.basePath);
} else {
newConfig.basePath = path.resolve(
namespacedBasePath,
config.basePath,
);
}
newConfig.basePath = path.resolve(
namespacedBasePath,
config.basePath,
);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolute paths wouldn't be converted to namespaced paths, and several tests would fail (on Windows):

1) ConfigArray
       Config objects `basePath` normalization
         should create a new object with namespaced `basePath` when normalizing absolute `basePath` on windows (async):

      AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
+ actual - expected

  {
+   basePath: 'C:\\foo',
-   basePath: '\\\\?\\C:\\foo',
    defs: {
      'test-def': 'test-value'
    }
  }

      + expected - actual

       {
      -  "basePath": "C:\\foo"
      +  "basePath": "\\\\?\\C:\\foo"
         "defs": {
           "test-def": "test-value"
         }
       }

      at Context.<anonymous> (file:///C:/projects/rewrite/packages/config-array/tests/config-array.test.js:827:11)

  2) ConfigArray
       Config objects `basePath` normalization
         should create a new object with namespaced `basePath` when normalizing absolute `basePath` on windows (sync):

      AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
+ actual - expected

  {
+   basePath: 'C:\\foo',
-   basePath: '\\\\?\\C:\\foo',
    defs: {
      'test-def': 'test-value'
    }
  }

      + expected - actual

       {
      -  "basePath": "C:\\foo"
      +  "basePath": "\\\\?\\C:\\foo"
         "defs": {
           "test-def": "test-value"
         }
       }

      at Context.<anonymous> (file:///C:/projects/rewrite/packages/config-array/tests/config-array.test.js:851:11)
      at process.processImmediate (node:internal/timers:491:21)

  3) ConfigArray
       ConfigArray members
         getConfigWithStatus()
           should return config without meta fields `name`, `basePath`, `files`, and `ignores`:

      AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
+ actual - expected

  {
+   status: 'unconfigured'
-   config: {
-     defs: {
-       'test-def': 'test-value'
-     }
-   },
-   status: 'matched'
  }

      + expected - actual

       {
      -  "status": "unconfigured"
      +  "config": {
      +    "defs": {
      +      "test-def": "test-value"
      +    }
      +  }
      +  "status": "matched"
       }

      at Context.<anonymous> (file:///C:/projects/rewrite/packages/config-array/tests/config-array.test.js:1034:12)
      at process.processImmediate (node:internal/timers:491:21)

  4) ConfigArray
       ConfigArray members
         isFileIgnored()
           config objects with `basePath` property
             should intepret `ignores` as relative to the config's `basePath` when ignoring directories (relative paths):

      AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

true !== false

      + expected - actual

      -true
      +false

      at Context.<anonymous> (file:///C:/projects/rewrite/packages/config-array/tests/config-array.test.js:4115:13)
      at process.processImmediate (node:internal/timers:491:21)

  5) ConfigArray
       ConfigArray members
         isFileIgnored()
           config objects with `basePath` property
             should intepret `ignores` as relative to the config's `basePath` when ignoring directories (absolute paths):

      AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

true !== false

      + expected - actual

      -true
      +false

      at Context.<anonymous> (file:///C:/projects/rewrite/packages/config-array/tests/config-array.test.js:4302:13)
      at process.processImmediate (node:internal/timers:491:21)

  6) ConfigArray
       ConfigArray members
         isFileIgnored()
           config objects with `basePath` property
             should intepret `ignores` as relative to the config's `basePath` when ignoring files (relative paths):

      AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

true !== false

      + expected - actual

      -true
      +false

      at Context.<anonymous> (file:///C:/projects/rewrite/packages/config-array/tests/config-array.test.js:4593:13)
      at process.processImmediate (node:internal/timers:491:21)

  7) ConfigArray
       ConfigArray members
         isFileIgnored()
           config objects with `basePath` property
             should intepret `ignores` as relative to the config's `basePath` when ignoring files (absolute paths):

      AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

true !== false

      + expected - actual

      -true
      +false

      at Context.<anonymous> (file:///C:/projects/rewrite/packages/config-array/tests/config-array.test.js:4823:13)
      at process.processImmediate (node:internal/timers:491:21)

  8) ConfigArray
       ConfigArray members
         isDirectoryIgnored()
           config objects with `basePath` property
             should intepret `ignores` as relative to the config's `basePath` (relative paths):

      AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

true !== false

      + expected - actual

      -true
      +false

      at Context.<anonymous> (file:///C:/projects/rewrite/packages/config-array/tests/config-array.test.js:5700:13)
      at process.processImmediate (node:internal/timers:491:21)

  9) ConfigArray
       ConfigArray members
         isDirectoryIgnored()
           config objects with `basePath` property
             should intepret `ignores` as relative to the config's `basePath` (absolute paths):

      AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

true !== false

      + expected - actual

      -true
      +false

      at Context.<anonymous> (file:///C:/projects/rewrite/packages/config-array/tests/config-array.test.js:5865:13)
      at process.processImmediate (node:internal/timers:491:21)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. It guess I was running the wrong tests when I checked this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we add basePath to the list of properties not included in the object returned by getConfig()?

- The returned config object never has `files`, `ignores`, or `name` properties; the only properties on the object will be the other configuration options specified.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in 82d07fd.

Copy link
Member

@fasttime fasttime left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@fasttime fasttime merged commit 40d31ba into main Jun 25, 2025
21 checks passed
@fasttime fasttime deleted the rfc131 branch June 25, 2025 08:10
@github-project-automation github-project-automation bot moved this from Implementing to Complete in Triage Jun 25, 2025
@github-actions github-actions bot mentioned this pull request Jun 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Complete
Development

Successfully merging this pull request may close these issues.

3 participants