fix(eslint-config): top-level export; move plugins to peerDeps#9
fix(eslint-config): top-level export; move plugins to peerDeps#9mikecbrant merged 6 commits intomainfrom
Conversation
…plugins to peerDeps per appsyncjs PR #29 and use ^X.Y.Z ranges
There was a problem hiding this comment.
No issues found with the changes. The move to peerDependencies for ESLint and plugins is appropriate for a shared config, and adding them to devDependencies preserves local development workflows. The lockfile changes are consistent with the package.json updates.
Summary of changes
- Moved all ESLint-related packages from
dependenciestopeerDependenciesinpackages/eslint-config/package.json. - Duplicated those packages under
devDependenciesto enable local linting during config development. - Kept
exports..pointing to./index.mjsand maintained thefileslist. - Updated
pnpm-lock.yamlimporter forpackages/eslint-configto reflect the shift fromdependenciestodevDependenciesand include the workspace Prettier config underdevDependencies.
See also: the lockfile updates aligning with the new dependency semantics.
There was a problem hiding this comment.
- The shift from
dependenciestopeerDependenciesis a breaking change and should be released as a major version to prevent consumer surprise. - Optionally consider adding
typescriptas an explicitpeerDependencyto make consumer requirements clearer (the@typescript-eslintpackages already imply this, but being explicit helps DX). - Lockfile updates appear consistent with the
package.jsonchanges.
Additional notes (1)
- Maintainability |
packages/eslint-config/package.json:24-32
Consider declaringtypescriptas an explicitpeerDependencyfor clearer consumer guidance, since@typescript-eslint/*plugins require it. This avoids peer resolution warnings surfacing only via transitive peer requirements and makes the expected install set explicit for users of this shared config.
Summary of changes
- Switched
packages/eslint-config/package.jsonfromdependenciestopeerDependenciesfor ESLint and all plugins, and duplicated them underdevDependenciesfor local development. - Kept package
exportspointing.to./index.mjsand preserved thefileslist. - Updated
pnpm-lock.yamlto reflect the above changes, moving entries under the importerpackages/eslint-configfromdependenciestodevDependencies.
See also: top-level flat config remains exported via index.mjs as intended.
mikecbrant
left a comment
There was a problem hiding this comment.
@CharlieHelps Please address feedback comment and ensure that this package gets a patch bump via changesets
…patch changeset for @mikecbrant/eslint-config
There was a problem hiding this comment.
- Moving ESLint and plugins from
dependenciestopeerDependenciesis a breaking change; releasing this as a patch is incorrect and risks consumer breakage. Update the changeset to a major bump and clearly document the breaking change. - Optionally add
typescriptas an explicitpeerDependency(and pin it indevDependencies) to make consumer requirements unambiguous and improve DX.
Additional notes (1)
- Maintainability |
packages/eslint-config/package.json:12-12
Consider declaringtypescriptas an explicit peer to make consumer requirements clear, since@typescript-eslint/*packages require it. This improves DX by surfacing the need to install TypeScript directly rather than via transitive peer warnings and aligns with the pattern you’ve applied to the other ESLint-related packages.
Summary of changes
- Switched
packages/eslint-config/package.jsonfromdependenciestopeerDependenciesfor ESLint core and all related plugins/configs. - Added pinned
devDependenciesfor local development of the config (mirroring the peer set) and kept@mikecbrant/prettier-configasworkspace:*. - Introduced a new changeset
.changeset/align-eslint-config-devdeps.mdmarking a patch bump and describing devDependency alignment. - Updated
pnpm-lock.yamlto reflect the dependency category changes and pinned versions under thepackages/eslint-configimporter.
| --- | ||
| "@mikecbrant/eslint-config": patch | ||
| --- | ||
|
|
||
| Align devDependency versions with the exact resolutions in the workspace lockfile for `packages/eslint-config` (ESLint core and all related plugins/configs). Peer dependency ranges remain as explicit compatible majors (using `^X.Y.Z`). |
There was a problem hiding this comment.
Marking this as a patch contradicts the consumer-facing breaking change introduced by moving ESLint and all plugins from dependencies to peerDependencies. Consumers that previously relied on transitive installs will now need to explicitly install these packages, which is a breaking change and should be released as a major to avoid surprise and align with semver expectations.
Suggestion
Change the changeset to a major bump and call out the breaking change explicitly, e.g.:
"@mikecbrant/eslint-config": major
Move ESLint core and all ESLint plugin/config packages from dependencies to peerDependencies. This is a breaking change: consumers must now install these as direct dependencies in their projects (e.g., eslint, @typescript-eslint/parser, @typescript-eslint/eslint-plugin, eslint-config-xo-typescript, eslint-plugin-import, eslint-import-resolver-typescript, eslint-plugin-unicorn, eslint-plugin-sonarjs, eslint-plugin-unused-imports). Also align devDependencies in this package to the exact workspace lockfile resolutions for local development.
Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this change.
There was a problem hiding this comment.
@CharlieHelps CHange this to major bump per your suggestion
There was a problem hiding this comment.
Expand this to see my work.
- Changed the front matter in
.changeset/align-eslint-config-devdeps.mdto set"@mikecbrant/eslint-config": majorinstead ofpatch. - Updated the summary to call out that consumers must now install
eslintand all moved plugins/configs viapeerDependencies, listing:eslint,@typescript-eslint/parser,@typescript-eslint/eslint-plugin,eslint-config-xo-typescript,eslint-plugin-import,eslint-import-resolver-typescript,eslint-plugin-unicorn,eslint-plugin-sonarjs,eslint-plugin-unused-imports. - Retained the note about aligning this package’s
devDependencieswith the exact workspace lockfile resolutions for local development. - Ran
pnpm -s -F @mikecbrant/eslint-config exec eslint .in the package scope; it completed cleanly with 0 errors/warnings. - Ran
pnpm -w run typecheck:tsgo; it reported no TypeScript sources and exited successfully. - Verified no other files (e.g.,
package.jsonor the lockfile) were touched—only.changeset/align-eslint-config-devdeps.mdchanged.
There was a problem hiding this comment.
Updated the changeset to mark a major release and clearly document the breaking peerDependencies change.
Changes
- Edited .changeset/align-eslint-config-devdeps.md to:
- Change release type for
@mikecbrant/eslint-configfrompatchtomajor. - Call out the breaking change: ESLint core and plugins/configs moved from dependencies to peerDependencies, so consumers must install them directly.
- Explicitly list the affected packages:
eslint@typescript-eslint/parser@typescript-eslint/eslint-plugineslint-config-xo-typescripteslint-plugin-importeslint-import-resolver-typescripteslint-plugin-unicorneslint-plugin-sonarjseslint-plugin-unused-imports
- Retain the note that this package’s devDependencies are aligned to exact versions from the workspace lockfile for local development.
- Change release type for
Commit: 259b1d5
No changes were made to any package.json or the lockfile, per scope.
Verification
# Install (workspace)
$ pnpm install -w
# Prettier: All matched files use Prettier code style
$ pnpm -w run fmt:check
# ESLint (package scope): no findings
$ pnpm -s -F @mikecbrant/eslint-config exec eslint .
# TypeScript placeholder: no TS sources
$ pnpm -w run typecheck:tsgoRe-requested review and assigned the PR to @mikecbrant; also requested review from @CharlieHelps.
… peerDependencies change and retain devDeps lockfile alignment note
There was a problem hiding this comment.
Overall, the shift to peerDependencies and the major changeset are correct and well-executed. One improvement: declare typescript as an explicit peerDependency (and pin it in devDependencies) to make consumer requirements unambiguous and avoid indirect peer warnings. Consider adding a simple install command to the changeset for smoother migration. No functional issues found beyond this DX refinement.
Additional notes (2)
-
Readability |
.changeset/align-eslint-config-devdeps.md:5-17
The changeset does a solid job calling out the breaking change and enumerating required packages. To improve migration clarity, consider includingtypescriptin the required list (it’s needed by@typescript-eslint/*) and adding a one-liner install command so consumers can copy/paste the exact set to install. -
Maintainability |
packages/eslint-config/package.json:23-32
Since you’re pinning local dev tooling to exact versions, addingtypescripthere will keep local linting and parser behavior consistent with what the plugins expect, and it mirrors the suggested peer addition.
Summary of changes
- Added a major changeset (.changeset/align-eslint-config-devdeps.md) documenting the breaking move of ESLint core/plugins from
dependenciestopeerDependenciesand the alignment of localdevDependenciesto lockfile versions. - Switched packages/eslint-config/package.json from
dependenciestopeerDependenciesfor ESLint and all related plugins/configs and pinned the same set underdevDependenciesfor local development. - Updated pnpm-lock.yaml importer for packages/eslint-config to reflect the shift to
devDependenciesand exact pinned versions, including the workspace Prettier config link under devDependencies. - Kept package root export to
./index.mjsand retained the files list.
…ency\n\n- peerDependencies: typescript ^5.0.0\n- devDependencies: typescript 5.9.2 (pinned to workspace lockfile resolution)\n\nRefs PR #9 review (id: 2325062722).
There was a problem hiding this comment.
The changes are largely correct and well-aligned with best practices for shared ESLint configs. One notable gap: the major Changeset does not mention typescript despite it being added as a peerDependency, which can confuse consumers during migration. Updating the Changeset to include typescript and a simple install command would improve clarity and DX. No other issues found in the package.json or lockfile changes.
Summary of changes
- Introduced a major Changeset (.changeset/align-eslint-config-devdeps.md) documenting the breaking move of ESLint core/plugins from
dependenciestopeerDependenciesand the alignment of localdevDependenciesto exact lockfile versions. - Switched packages/eslint-config/package.json from
dependenciestopeerDependencies, addedtypescriptas an explicit peer (^5.0.0), and pinned the same set underdevDependencies(includingtypescript@5.9.2) for local development. - Updated pnpm-lock.yaml importer for packages/eslint-config to reflect the shift to
devDependencieswith exact specifiers and addedtypescriptunder devDependencies. - Kept package root export (
exports..->./index.mjs) and the publishedfileslist unchanged.
| Breaking change: move ESLint core and all ESLint plugin/config packages from `dependencies` to `peerDependencies`. Consumers must now install these directly in their projects to use this shared config: | ||
|
|
||
| - `eslint` | ||
| - `@typescript-eslint/parser` | ||
| - `@typescript-eslint/eslint-plugin` | ||
| - `eslint-config-xo-typescript` | ||
| - `eslint-plugin-import` | ||
| - `eslint-import-resolver-typescript` | ||
| - `eslint-plugin-unicorn` | ||
| - `eslint-plugin-sonarjs` | ||
| - `eslint-plugin-unused-imports` | ||
|
|
||
| Also align this package’s `devDependencies` with the exact versions resolved in the workspace lockfile to support local development of the config. |
There was a problem hiding this comment.
The Changeset correctly marks this as a major release and lists required packages, but it omits typescript, which is now a declared peer. This can mislead consumers during migration and degrade DX. Including typescript in the required list (and a copy/paste install command) makes the breaking change unambiguous and eases adoption.
Suggestion
Consider updating the Changeset to include typescript in the required list and add a one-liner install command to streamline migration:
- Add a bullet for
typescriptin the list. - Append a short "Install" example, e.g.:
- `typescript`
Install (example):
pnpm add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-xo-typescript eslint-plugin-import eslint-import-resolver-typescript eslint-plugin-unicorn eslint-plugin-sonarjs eslint-plugin-unused-imports typescriptReply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion.
There was a problem hiding this comment.
@CharlieHelps I would actually like to update the peer dependencies here to minimize peer deps that consumer has to install. typescript should definitely be a peer dep, but possibly eslint needs to be one as well (I would like to be typescript only if possible). All the other eslint shared configs should be a prod dependency of this package so they are installed for the consumer.
This would still require breaking change.
There was a problem hiding this comment.
All done.
There was a problem hiding this comment.
Thanks for the clarification. To minimize what consumers must install directly, here are two concrete options—please confirm which you want me to implement:
-
Option A (preferred): Only TypeScript is a peer
- peerDependencies: typescript (keep the existing range from the PR, e.g., ^5.0.0)
- dependencies: eslint core + all ESLint plugins/configs currently listed
- eslint
- @typescript-eslint/parser
- @typescript-eslint/eslint-plugin
- eslint-config-xo-typescript
- eslint-plugin-import
- eslint-import-resolver-typescript
- eslint-plugin-unicorn
- eslint-plugin-sonarjs
- eslint-plugin-unused-imports
- devDependencies: keep a pinned typescript (matching the workspace lockfile, e.g., 5.9.2); remove pinned entries for the above packages since they move to dependencies
- Changeset: breaking change note will say “only typescript must be installed directly; all other ESLint packages are now transitive deps of @mikecbrant/eslint-config”
-
Option B: TypeScript and ESLint are peers
- peerDependencies: typescript (e.g., ^5.0.0) and eslint (use the existing PR range, e.g., ^9.0.0)
- dependencies: the ESLint plugins/configs listed above (not eslint core)
- devDependencies: keep pinned typescript and eslint (matching the lockfile, e.g., typescript 5.9.2, eslint 9.34.0)
- Changeset: breaking change note will say “typescript and eslint must be installed directly; plugins/configs are transitive deps”
Notes
- I will preserve the exact semver ranges currently used in the PR when moving packages between categories.
- I’ll update packages/eslint-config/package.json, pnpm-lock.yaml (importer for this package), the major Changeset text, and refresh the PR description to match the chosen model.
Please confirm Option A or Option B. Once confirmed, I’ll make the edits and push.
Small CLI nuance (pnpm)
If eslint is not a direct dependency of a consumer project (Option A), pnpm may not link the eslint binary to the project’s .bin. Teams that invoke eslint via a local script might still choose to keep eslint as a direct devDependency. Option B avoids this by requiring eslint as a peer.There was a problem hiding this comment.
@CharlieHelps Let's take option B and make eslint a peer. Thanks for the CLI nuance comment as this was important.
For our prod and dev deps I do not want pinned versions, but rather caret versions so we will always be working and testing with current versions.
I would love for the README file for this package to include commentary that typescript and eslint are peer deps that should be installed alongside this lint package. The README should also include example of using in consumer - i.e. how to create local eslint.config file that utilizes this shared config and instructs on how to avoid issues we had to resolve in recent PR for this repo around duplicated config values in the flatfile export.
There was a problem hiding this comment.
Expand this to see my work.
- Cataloged plugin/config usage in
packages/eslint-config/config.mjsandpackages/eslint-config/eslint.config.mjsto move todependencies:@typescript-eslint/eslint-plugin,@typescript-eslint/parser,eslint-config-xo-typescript,eslint-plugin-import,eslint-import-resolver-typescript,eslint-plugin-unicorn,eslint-plugin-sonarjs,eslint-plugin-unused-imports. - Verified workspace context in root
package.jsonand confirmed top-level export inpackages/eslint-config/index.mjsunchanged by recategorization. - Confirmed target peer and dev ranges for
packages/eslint-config/package.json:peerDependencies→eslint^9.0.0,typescript^5.0.0;devDependencies→eslint^9.34.0,typescript^5.9.2, keeping@mikecbrant/prettier-configworkspace:*. - Updated
packages/eslint-config/package.jsonto set onlyeslint^9.0.0andtypescript^5.0.0inpeerDependencies, moved all ESLint plugins/configs todependencieswith caret ranges, and trimmeddevDependenciesaccordingly. - Rewrote
.changeset/align-eslint-config-devdeps.md(major) to state onlyeslintandtypescriptare required peers and that plugins/configs install transitively; updated policy to caret-baseddevDependencies. - Updated
packages/eslint-config/README.mdwith a Peer dependencies section (eslint^9.0.0,typescript^5.0.0), install example including those peers, a minimaleslint.config.mjsusage import from@mikecbrant/eslint-config, and guidance to avoid duplicating rules/plugins already provided. - Refreshed
pnpm-lock.yamlimporter forpackages/eslint-configso plugins/configs appear underdependencieswith caret specifiers andeslint/typescriptunderdevDependencies, removing obsolete pinned entries. - Ran
eslintandfmt:checkinpackages/eslint-config;eslintran clean,fmt:checkpassed; type check reports no-op (no TS sources). - Committed changes in ed361e3 and pushed to branch
ai-8-update-shared-eslint-configlinked to PR #9. - Considered review suggestions to pin plugin versions and, per the decision in PR #9, retained caret ranges in
dependenciesas required.
There was a problem hiding this comment.
Implemented Option B for @mikecbrant/eslint-config and switched prod/dev specs to caret ranges. This applies the owner’s decision in PR #9 and the follow-up requirements.
- Commit: ed361e3
- PR description updated to reflect Option B and caret policy
- Reviews re-requested from @mikecbrant and @CharlieHelps
Changes
- packages/eslint-config/package.json
- peerDependencies: only
- eslint: ^9.0.0
- typescript: ^5.0.0
- dependencies (caret ranges):
- @typescript-eslint/parser: ^8.41.0
- @typescript-eslint/eslint-plugin: ^8.41.0
- eslint-config-xo-typescript: ^8.0.2
- eslint-plugin-import: ^2.32.0
- eslint-import-resolver-typescript: ^3.10.1
- eslint-plugin-unicorn: ^52.0.0
- eslint-plugin-sonarjs: ^3.0.5
- eslint-plugin-unused-imports: ^4.2.0
- devDependencies (caret ranges only for local dev):
- eslint: ^9.34.0
- typescript: ^5.9.2
- keep @mikecbrant/prettier-config: workspace:*
- peerDependencies: only
- .changeset/align-eslint-config-devdeps.md
- Kept as major
- Updated to Option B: only eslint and typescript are peers; plugins/configs are now regular deps installed transitively
- Updated policy note: devDependencies now use caret ranges (no pinning)
- packages/eslint-config/README.md
- Added Peer dependencies section (eslint ^9.0.0, typescript ^5.0.0)
- Updated Install example: pnpm add -D eslint typescript @mikecbrant/eslint-config
- Minimal Usage example (flat config import/export)
- Guidance to avoid duplicating plugins/rules in consumer flat configs
- pnpm-lock.yaml
- Importer for packages/eslint-config now reflects:
- plugins/configs under dependencies with caret specifiers
- eslint and typescript under devDependencies with caret specifiers
- Importer for packages/eslint-config now reflects:
Verification
# Install / lockfile refresh
$ pnpm install -w
# Result: up to date; importer updated to new deps/devDeps layout
# Prettier
$ pnpm -w run fmt:check
# Result: All matched files use Prettier code style
# ESLint (package scope)
$ pnpm -s -F @mikecbrant/eslint-config exec eslint .
# Result: OK
# TypeScript placeholder (no TS sources in this repo)
$ pnpm -w run typecheck:tsgo
# Result: tsgo: no-op (no TS sources in this repo)Notes
- Followed the owner’s instruction to use caret ranges for both prod and dev tooling.
- No changes to exports or published files list.
…gins as deps; caret ranges\n\n- peerDependencies: eslint ^9.0.0, typescript ^5.0.0 only\n- dependencies: move ESLint plugins/configs; use caret ranges per owner\n- devDependencies: eslint ^9.34.0, typescript ^5.9.2, keep @mikecbrant/prettier-config workspace:*\n- update Changeset to state Option B and caret devDeps policy\n- docs: README adds peers, install/usage, and guidance to avoid duplicated flat-config values
There was a problem hiding this comment.
- Option B dependency model is implemented correctly and reflected in the lockfile and README.
- The Changeset clearly describes peers vs dependencies; adding a copy/paste install command would improve migration clarity.
- README guidance is solid; minor DX improvements suggested: clarify config filename (
.jsvs.mjs) and explicitly mention the XO TypeScript preset in the “Avoid duplicated config values” section. - No functional or performance issues detected in the package.json or lockfile changes.
Additional notes (3)
-
Readability |
.changeset/align-eslint-config-devdeps.md:9-9
Consider adding a short, copy/paste install command to make the migration path explicit for consumers under Option B. This will reduce friction and avoid misinstalls when upgrading to the new major. -
Readability |
packages/eslint-config/README.md:24-25
The updated install text is helpful. A brief note about which config filename to use in ESM vs non-ESM projects would further reduce setup confusion with ESLint 9 flat configs. -
Maintainability |
packages/eslint-config/README.md:37-45
Great call-out to avoid duplicating plugins/config values. Since this package also encapsulates the XO TypeScript preset, explicitly mentioning it here will help prevent users from redundantly extending it and causing conflicts.
Summary of changes
- Adopted Option B dependency model: only
eslintandtypescriptarepeerDependencies; all ESLint plugins/configs moved to regulardependencies. - Updated packages/eslint-config/package.json:
- Added
peerDependencies:eslint(^9.0.0) andtypescript(^5.0.0) - Moved ESLint plugins/configs to
dependencieswith caret ranges (e.g.,@typescript-eslint/*,eslint-config-xo-typescript,eslint-plugin-*) - Set
devDependenciesto caret ranges foreslintandtypescriptand retained the workspace Prettier config
- Added
- Added a major Changeset documenting Option B and the caret devDependencies policy.
- Expanded README with Peer dependencies section, updated install command to include peers, and guidance to avoid duplicated flat-config values.
- Updated pnpm-lock.yaml importer for
packages/eslint-configto reflect new dependency categories and caret specifiers.
Adopts Option B for
@mikecbrant/eslint-config: keep onlyeslintandtypescriptas peers; ship all ESLint plugins/configs as dependencies. Also switch prod/dev specs to caret ranges, update the major Changeset text, and improve package README.Changes
eslint^9.0.0 andtypescript^5.0.0 only.@typescript-eslint/parser^8.41.0@typescript-eslint/eslint-plugin^8.41.0eslint-config-xo-typescript^8.0.2eslint-plugin-import^2.32.0eslint-import-resolver-typescript^3.10.1eslint-plugin-unicorn^52.0.0eslint-plugin-sonarjs^3.0.5eslint-plugin-unused-imports^4.2.0eslint^9.34.0,typescript^5.9.2, and keep@mikecbrant/prettier-configasworkspace:*..changeset/align-eslint-config-devdeps.mdto document Option B (onlyeslint+typescriptas peers) and note the caret policy for devDependencies.pnpm add -D eslint typescript @mikecbrant/eslint-config), minimal usage example, and notes to avoid duplicating plugins/rules in consumer flat configs.Verification
Implements the review decision in PR #9 to take Option B and use caret ranges for prod/dev tooling. PR updated accordingly.