chore: Upgrade Linting / Prettier packages#755
Conversation
🦋 Changeset detectedLatest commit: 7fa5e13 The changes in this PR will be included in the next version bump. This PR includes changesets to release 20 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub. |
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
📝 WalkthroughWalkthroughBatch upgrade of linting/formatting/tooling versions plus widespread code modernizations: optional chaining, toSorted immutability, String.raw regex fixes, minor API signature tweaks, component prop loosenings, environment port updates, and added/removed agent documentation and settings. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
No actionable comments were generated in the recent review. 🎉 🧹 Recent nitpick comments
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/project-builder-web/src/routes/data/models/edit.$key/-components/fields/primary-key/model-primary-key-form.tsx (1)
38-46:⚠️ Potential issue | 🔴 CriticalRestore the default empty array fallback to prevent undefined from propagating to the nested form.
The removal of the
= []default frommodelValuemeans that ifmodel.primaryKeyFieldRefsis undefined during form initialization (which is possible since the parent form might not initialize this field immediately), the nesteduseFormreceivesvalues: { fields: undefined }instead ofvalues: { fields: [] }. This causesMultiComboboxFieldControllerto initialize with an undefined value rather than an empty array, breaking the form's expected behavior.Proposed fix
const { - field: { value: modelValue, onChange: onModelChange }, + field: { value: modelValue = [], onChange: onModelChange }, } = useController({ name: 'model.primaryKeyFieldRefs', control: modelControl, });
🤖 Fix all issues with AI agents
In
`@examples/blog-with-auth/apps/admin/.baseplate-snapshot/diffs/package.json.diff`:
- Line 10: The addition of "msw": "2.12.4" in the package.json diff is outside
the stated linting/prettier upgrade scope; either remove the msw entry from this
changeset (undo the package.json addition in
examples/blog-with-auth/apps/admin/.baseplate-snapshot/diffs/package.json.diff)
or move it into its own changeset/PR with an appropriate title and changelog
entry so the msw dependency change is tracked separately from the lint/prettier
upgrade.
In `@examples/todo-with-auth0/apps/admin/src/services/sentry.ts`:
- Around line 24-25: The transaction name call uses a compile-time assertion
(error.path[0] as string) which can be a number at runtime; change the call in
scope.setTransactionName to coerce the value to a string at runtime (e.g., use
String(error.path[0])) while leaving scope.setTag('path', error.path.join('.'))
unchanged; update the code around scope.setTransactionName to use a runtime
string conversion so numeric path segments are handled safely.
In `@packages/code-morph/src/morphers/utils/imports.ts`:
- Line 81: The namedImports array is being sorted with the default .toSorted()
which is case-sensitive and inconsistent with other sorts that use
compareStrings; update the creation of namedImports in imports.ts (the line that
builds namedImports: namedImports.toSorted().map(...)) to call
.toSorted(compareStrings) using compareStrings imported from
`@baseplate-dev/utils` so import name ordering is deterministic and
case-insensitive, matching the sort used elsewhere (e.g., where compareStrings
is already applied).
In `@packages/core-generators/package.json`:
- Line 76: Revert the dependency version for prettier-plugin-packagejson back to
the published release by changing the version string for
"prettier-plugin-packagejson" in package.json from "3.0.0" to "2.5.19"; update
the dependency entry so package installation succeeds and run npm/yarn install
to verify.
In `@packages/project-builder-server/src/dev-server/mcp/mcp-server.int.test.ts`:
- Line 67: Update the trailing comment to reflect the actual timeout value:
change the comment after the test timeout numeric literal 20_000 to "20 second
timeout" (referring to the 20_000 value in the test block) so the comment
matches the code.
In `@packages/project-builder-server/src/diff/snapshot/snapshot-management.ts`:
- Around line 255-257: The logger.info calls that build section headers use
String.raw which prevents the \n from being interpreted, causing a literal "\n"
to be logged; update the three calls that reference
manifest.files.modified.length, manifest.files.added.length, and
manifest.files.removed.length to use normal template literals (or otherwise
prepend an actual newline string) instead of String.raw so the leading newline
is rendered as a real line break.
In `@packages/project-builder-web/src/routes/data/route.tsx`:
- Around line 30-33: The destructuring from useProjectDefinition removed the
default for models so the spread in longestName (using maxBy([...models,
...enums], ...)) will throw if models is undefined; restore a safe default by
providing models = [] (and optionally enums = []) in the destructuring from
useProjectDefinition or ensure the spread uses fallback arrays (e.g.,
useProjectDefinition -> definition: { models = [], enums = [] } or change the
array construction to use (models || []) and (enums || [])) so longestName and
maxBy operate on arrays safely.
In
`@packages/react-generators/src/generators/apollo/apollo-sentry/apollo-sentry.generator.ts`:
- Around line 49-50: Replace the unsafe cast on error.path[0] used in the
scope.setTransactionName call with an explicit string coercion; specifically, in
the apollo-sentry generator where scope.setTransactionName(error.path[0] as
string) is used, change it to use String(error.path[0]) (or a safe
optional-coercion variant) so numbers in ReadonlyArray<string|number> are
correctly converted to strings while leaving scope.setTag('path',
error.path.join('.')) as-is.
In `@packages/sync/src/output/prepare-generator-files/prepare-generator-file.ts`:
- Around line 86-90: The filter for formatters (formattersForFile) incorrectly
uses the nullish coalescing operator (??) between the fileExtensions check and
the fileNames check, which prevents evaluating fileNames when fileExtensions is
defined but doesn't match; change the expression to use a boolean OR (||)
between the two checks so a formatter matches if either
fileExtensions?.includes(path.extname(relativePath)) or
fileNames?.includes(path.basename(relativePath)) is true (preserve any explicit
boolean coercion if desired) to restore the original semantics.
In `@packages/tools/eslint-configs/react.js`:
- Around line 60-69: The config reference
reactHooksPlugin.configs.flat['recommended-latest'] is invalid; replace it with
the plugin's actual API, e.g., reactHooksPlugin.configs['recommended-latest']
(or reactHooksPlugin.configs['flat/recommended']) and keep the rules block that
disables 'react-hooks/refs', 'react-hooks/set-state-in-effect',
'react-hooks/preserve-manual-memoization', and
'react-hooks/incompatible-library' so the ESLint import uses a valid configs
property (update the reactHooksPlugin.configs[...] expression in the same object
where those rule names appear).
🧹 Nitpick comments (12)
plugins/plugin-auth/src/auth0/generators/react/auth0-hooks/auth0-hooks.generator.ts (1)
32-32: Redundant spread before.toSorted().
Array.prototype.toSorted()already returns a new array without mutating the original, so the[...authRoles]copy is unnecessary.♻️ Suggested simplification
- [...authRoles].toSorted().map((role) => quot(role)), + authRoles.toSorted().map((role) => quot(role)),packages/ui-components/src/components/ui/circular-progress/circular-progress.tsx (1)
3-11: Export theCircularProgressPropsinterface.As per coding guidelines, "If a particular interface or type is not exported, change the file so it is exported."
Proposed fix
-interface CircularProgressProps { +export interface CircularProgressProps {packages/project-builder-lib/src/definition/model/model-field-utils.ts (1)
29-33: Unnecessary spread beforetoSorted().
toSorted()already returns a new array without mutating the original, so the spread on lines 29 and 31 creates a redundant intermediate array. Lines 33 and 78 correctly calltoSorted()directly on the result of.map().♻️ Remove redundant spreads
- const sortedFieldIds = [...fieldIds].toSorted(); + const sortedFieldIds = fieldIds.toSorted(); return ( - (isEqual([...model.model.primaryKeyFieldRefs].toSorted(), sortedFieldIds) || + (isEqual(model.model.primaryKeyFieldRefs.toSorted(), sortedFieldIds) ||packages/project-builder-web/src/routes/admin-sections.$appKey/-components/new-admin-section-dialog.tsx (1)
32-38:NewAdminSectionDialogPropsis not exported.As per coding guidelines, "If a particular interface or type is not exported, change the file so it is exported."
Proposed fix
-interface NewAdminSectionDialogProps { +export interface NewAdminSectionDialogProps {packages/project-builder-lib/src/schema/models/authorizer/authorizer-expression-parser.ts (1)
57-57: Stale@paramin JSDoc.Line 54 still documents
@param _projectDefwhich no longer exists in the signature. Remove the stale@paramline.📝 Proposed fix
/** * Parse the expression string into an AST. * * `@param` value - The expression string - * `@param` _projectDef - The project definition (unused during parsing) * `@returns` The parsed expression info, or undefined if parsing fails */packages/project-builder-lib/src/plugins/spec/config-spec.ts (1)
33-35: Redundant spread beforetoSorted.
toSortedalready returns a new array without mutating the original, so the[...migrations]spread is unnecessary.♻️ Suggested simplification
- const sortedMigrations = [...migrations].toSorted( + const sortedMigrations = migrations.toSorted( (a, b) => a.version - b.version, );packages/core-generators/src/renderers/typescript/extractor/render-ts-template-renderers.ts (1)
48-48: UsecompareStringsfor sorting provider names in code generation.The default
.toSorted()uses lexicographic comparison which is case-sensitive (Abeforea). For code generation contexts, the codebase convention is to usecompareStringsfrom@baseplate-dev/utilsfor deterministic sorting.Suggested fix
+import { compareStrings } from '@baseplate-dev/utils'; + // ... - ${[...new Set(providers.map((p) => p.replace(/Provider$/, '')))].toSorted().join(', ')} + ${[...new Set(providers.map((p) => p.replace(/Provider$/, '')))].toSorted(compareStrings).join(', ')}As per coding guidelines: "Always use
compareStringsfrom@baseplate-dev/utilsinstead ofString.prototype.localeCompare()for code generation, file sorting, and internal data structures."packages/core-generators/src/renderers/extractor/plugins/barrel-export.ts (1)
119-119: Consider usingcompareStringsfor all sorting in code generation output.Multiple
.toSorted()calls here use default lexicographic comparison. For code generation contexts, the codebase convention is to usecompareStringsfrom@baseplate-dev/utilsfor deterministic, case-insensitive sorting. This applies to Lines 119, 150, 159, 206–208, 212, and 232.As per coding guidelines: "Always use
compareStringsfrom@baseplate-dev/utilsinstead ofString.prototype.localeCompare()for code generation, file sorting, and internal data structures."Also applies to: 150-150, 159-159, 206-212, 232-232
examples/todo-with-auth0/apps/web/src/components/ui/circular-progress.tsx (1)
3-11: Export theCircularProgressPropsinterface.The coding guidelines require that interfaces be exported. This applies to all three
circular-progress.tsxfiles in this PR.Proposed fix
-interface CircularProgressProps { +export interface CircularProgressProps {As per coding guidelines, "If a particular interface or type is not exported, change the file so it is exported."
examples/todo-with-auth0/apps/admin/src/components/ui/circular-progress.tsx (1)
3-11: Export theCircularProgressPropsinterface.Same as the
webvariant — the interface should be exported per coding guidelines.Proposed fix
-interface CircularProgressProps { +export interface CircularProgressProps {As per coding guidelines, "If a particular interface or type is not exported, change the file so it is exported."
packages/react-generators/src/generators/core/react-components/templates/components/ui/circular-progress.tsx (1)
5-13: Export theCircularProgressPropsinterface in the template.This is the generator template that produces the example files. Exporting here would propagate to all generated instances.
Proposed fix
-interface CircularProgressProps { +export interface CircularProgressProps {As per coding guidelines, "If a particular interface or type is not exported, change the file so it is exported."
packages/utils/src/toposort/toposort.unit.test.ts (1)
119-142: Redundant double invocation oftoposortcould be consolidated.Each error-property test calls
toposorttwice — once viaexpect().toThrow()and again inside atry/catch. You could combine both into a single invocation:♻️ Example consolidation (applies to all similar tests in this file)
- expect(() => toposort(nodes, edges)).toThrow( - ToposortCyclicalDependencyError, - ); - - // Verify cycle path properties - let error: ToposortCyclicalDependencyError | null = null; - try { - toposort(nodes, edges); - } catch (e) { - error = e as ToposortCyclicalDependencyError; - } + let error: ToposortCyclicalDependencyError | null = null; + try { + toposort(nodes, edges); + expect.unreachable('Expected ToposortCyclicalDependencyError to be thrown'); + } catch (e) { + expect(e).toBeInstanceOf(ToposortCyclicalDependencyError); + error = e as ToposortCyclicalDependencyError; + }This is a minor style nit — the current approach is functionally correct and arguably more readable with the separate
toThrowassertion. Feel free to keep as-is.
| "eslint-plugin-react-hooks": "7.0.1", | ||
| "eslint-plugin-unicorn": "62.0.0", | ||
| "globals": "17.3.0", | ||
| + "msw": "2.12.4", |
There was a problem hiding this comment.
msw addition appears unrelated to the linting/prettier upgrade scope.
The PR title and changeset describe a linting/prettier package upgrade, but msw (Mock Service Worker) is a testing utility unrelated to linting or formatting. Is this intentional, or should it be in a separate changeset?
🤖 Prompt for AI Agents
In
`@examples/blog-with-auth/apps/admin/.baseplate-snapshot/diffs/package.json.diff`
at line 10, The addition of "msw": "2.12.4" in the package.json diff is outside
the stated linting/prettier upgrade scope; either remove the msw entry from this
changeset (undo the package.json addition in
examples/blog-with-auth/apps/admin/.baseplate-snapshot/diffs/package.json.diff)
or move it into its own changeset/PR with an appropriate title and changelog
entry so the msw dependency change is tracked separately from the lint/prettier
upgrade.
| scope.setTransactionName(error.path[0] as string); | ||
| scope.setTag('path', error.path.join('.')); |
There was a problem hiding this comment.
as string on a potentially numeric path segment is less safe than String().
error.path is typed as ReadonlyArray<string | number> — path segments can be numeric array indices. The previous String(error.path[0]) performed a runtime conversion, guaranteeing a string value at runtime. The new as string is a compile-time-only assertion that silently passes a number through to setTransactionName.
Line 25's change is fine since .join('.') already returns a string.
Suggested fix
- scope.setTransactionName(error.path[0] as string);
+ scope.setTransactionName(String(error.path[0]));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| scope.setTransactionName(error.path[0] as string); | |
| scope.setTag('path', error.path.join('.')); | |
| scope.setTransactionName(String(error.path[0])); | |
| scope.setTag('path', error.path.join('.')); |
🤖 Prompt for AI Agents
In `@examples/todo-with-auth0/apps/admin/src/services/sentry.ts` around lines 24 -
25, The transaction name call uses a compile-time assertion (error.path[0] as
string) which can be a number at runtime; change the call in
scope.setTransactionName to coerce the value to a string at runtime (e.g., use
String(error.path[0])) while leaving scope.setTag('path', error.path.join('.'))
unchanged; update the code around scope.setTransactionName to use a runtime
string conversion so numeric path segments are handled safely.
| "p-limit": "6.1.0", | ||
| "prettier": "catalog:", | ||
| "prettier-plugin-packagejson": "2.5.19", | ||
| "prettier-plugin-packagejson": "3.0.0", |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
prettier-plugin-packagejson 3.0.0 breaking changes release notes
💡 Result:
I couldn’t find any prettier-plugin-packagejson 3.0.0 release (or release notes / changelog for it). The package’s published versions appear to top out at 2.5.19 (released July 20, 2025) with latest = 2.5.19, and no 3.x line is listed. [1] [2]
If you’re upgrading in the context of Prettier v3, note that the plugin’s docs explicitly call out that you must add it to plugins in your Prettier config for Prettier 3+ (this is often the “breaking” behavior people hit when moving to Prettier 3). [1]
Sources
[1] (npmjs.com)
[2] (classic.yarnpkg.com)
Citations:
- 1: https://www.npmjs.com/package/prettier-plugin-packagejson?utm_source=openai
- 2: https://classic.yarnpkg.com/en/package/prettier-plugin-packagejson?utm_source=openai
🏁 Script executed:
# Search for prettier-plugin-packagejson usage in the codebase
rg "prettier-plugin-packagejson" --type json --type js --type ts --type mdRepository: halfdomelabs/baseplate
Length of output: 3128
🏁 Script executed:
# Check for prettier configuration files
fd -e ".prettierrc*" -e "prettier.config.*"Repository: halfdomelabs/baseplate
Length of output: 48
🏁 Script executed:
# Check how prettier is configured in package.json or other config files
cat packages/core-generators/package.json | grep -A 20 -B 5 "prettier"Repository: halfdomelabs/baseplate
Length of output: 1548
Revert prettier-plugin-packagejson to version 2.5.19 — version 3.0.0 does not exist on npm. The latest published version is 2.5.19, and attempting to install 3.0.0 will cause installation to fail.
🤖 Prompt for AI Agents
In `@packages/core-generators/package.json` at line 76, Revert the dependency
version for prettier-plugin-packagejson back to the published release by
changing the version string for "prettier-plugin-packagejson" in package.json
from "3.0.0" to "2.5.19"; update the dependency entry so package installation
succeeds and run npm/yarn install to verify.
| ), | ||
| ).toBe(true); | ||
| }, 10_000); // 10 second timeout | ||
| }, 20_000); // 10 second timeout |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the test file to confirm the timeout value at line 67
cat -n packages/project-builder-server/src/dev-server/mcp/mcp-server.int.test.ts | sed -n '60,75p'Repository: halfdomelabs/baseplate
Length of output: 420
🏁 Script executed:
# Check git history for context on timeout changes
cd packages/project-builder-server/src/dev-server/mcp && \
git log --oneline --all -- mcp-server.int.test.ts | head -20Repository: halfdomelabs/baseplate
Length of output: 269
🏁 Script executed:
# Let's check the specific commit that changed the timeout
git log -p --all -- packages/project-builder-server/src/dev-server/mcp/mcp-server.int.test.ts | grep -A 5 -B 5 "20_000\|10_000" | head -50Repository: halfdomelabs/baseplate
Length of output: 48
🏁 Script executed:
# Search for any mentions of timeout issues or flakiness in recent commits
git log --all --oneline | grep -i "timeout\|flak\|slow\|perform" | head -20Repository: halfdomelabs/baseplate
Length of output: 196
🏁 Script executed:
# Find the specific commit that changed the timeout value for this test
git log -p --all -- packages/project-builder-server/src/dev-server/mcp/mcp-server.int.test.ts | grep -A 10 -B 10 "20_000\|10_000" | head -100Repository: halfdomelabs/baseplate
Length of output: 48
🏁 Script executed:
# Check if there were any recent changes to this specific test
git show HEAD:packages/project-builder-server/src/dev-server/mcp/mcp-server.int.test.ts | sed -n '60,75p'Repository: halfdomelabs/baseplate
Length of output: 357
🏁 Script executed:
# Search for any test timeout configuration or constants
rg "timeout|20_000|10_000" packages/project-builder-server/src/dev-server/mcp/ -A 2 -B 2Repository: halfdomelabs/baseplate
Length of output: 427
Update the comment to match the timeout value.
The comment says "10 second timeout" but the actual timeout is now 20 seconds (20,000ms).
- }, 20_000); // 10 second timeout
+ }, 20_000); // 20 second timeout📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| }, 20_000); // 10 second timeout | |
| }, 20_000); // 20 second timeout |
🤖 Prompt for AI Agents
In `@packages/project-builder-server/src/dev-server/mcp/mcp-server.int.test.ts` at
line 67, Update the trailing comment to reflect the actual timeout value: change
the comment after the test timeout numeric literal 20_000 to "20 second timeout"
(referring to the 20_000 value in the test block) so the comment matches the
code.
| definition: { models, enums = [] }, | ||
| } = useProjectDefinition(); | ||
|
|
||
| const longestName = maxBy([...models, ...enums], (m) => m.name.length)?.name; |
There was a problem hiding this comment.
models lost its = [] default — spreading it on line 33 will throw if undefined.
The previous code defaulted models to []. With that default removed, [...models, ...enums] will throw a TypeError at runtime when models is undefined.
🐛 Proposed fix: restore the default
- definition: { models, enums = [] },
+ definition: { models = [], enums = [] },📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| definition: { models, enums = [] }, | |
| } = useProjectDefinition(); | |
| const longestName = maxBy([...models, ...enums], (m) => m.name.length)?.name; | |
| definition: { models = [], enums = [] }, | |
| } = useProjectDefinition(); | |
| const longestName = maxBy([...models, ...enums], (m) => m.name.length)?.name; |
🤖 Prompt for AI Agents
In `@packages/project-builder-web/src/routes/data/route.tsx` around lines 30 - 33,
The destructuring from useProjectDefinition removed the default for models so
the spread in longestName (using maxBy([...models, ...enums], ...)) will throw
if models is undefined; restore a safe default by providing models = [] (and
optionally enums = []) in the destructuring from useProjectDefinition or ensure
the spread uses fallback arrays (e.g., useProjectDefinition -> definition: {
models = [], enums = [] } or change the array construction to use (models || [])
and (enums || [])) so longestName and maxBy operate on arrays safely.
| scope.setTransactionName(error.path[0] as string); | ||
| scope.setTag('path', error.path.join('.')); |
There was a problem hiding this comment.
as string cast on error.path[0] is less safe than the previous String() call.
error.path is typed as ReadonlyArray<string | number>, so error.path[0] can be a number (array index in the GraphQL path). The old String(error.path[0]) would safely coerce a number to a string at runtime, while as string silently lies to the compiler and passes a number where a string is expected.
Line 50 change is fine — .join('.') already returns string, so removing the String() wrapper is correct.
Since the first path element is almost always the root field name (a string) in practice, this is low risk, but worth noting.
Proposed fix
- scope.setTransactionName(error.path[0] as string);
+ scope.setTransactionName(String(error.path[0]));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| scope.setTransactionName(error.path[0] as string); | |
| scope.setTag('path', error.path.join('.')); | |
| scope.setTransactionName(String(error.path[0])); | |
| scope.setTag('path', error.path.join('.')); |
🤖 Prompt for AI Agents
In
`@packages/react-generators/src/generators/apollo/apollo-sentry/apollo-sentry.generator.ts`
around lines 49 - 50, Replace the unsafe cast on error.path[0] used in the
scope.setTransactionName call with an explicit string coercion; specifically, in
the apollo-sentry generator where scope.setTransactionName(error.path[0] as
string) is used, change it to use String(error.path[0]) (or a safe
optional-coercion variant) so numbers in ReadonlyArray<string|number> are
correctly converted to strings while leaving scope.setTag('path',
error.path.join('.')) as-is.
| reactHooksPlugin.configs.flat['recommended-latest'], | ||
| { | ||
| rules: { | ||
| // Disable new strict rules from react-hooks v7 until we enable React Compiler | ||
| 'react-hooks/refs': 'off', | ||
| 'react-hooks/set-state-in-effect': 'off', | ||
| 'react-hooks/preserve-manual-memoization': 'off', | ||
| 'react-hooks/incompatible-library': 'off', | ||
| }, | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n packages/tools/eslint-configs/react.jsRepository: halfdomelabs/baseplate
Length of output: 3335
🌐 Web query:
eslint-plugin-react-hooks v7 API release notes configs.flat
💡 Result:
As of Feb 11, 2026, there is no published eslint-plugin-react-hooks v7 and therefore no “v7 API release notes” for a configs.flat API.
What the plugin actually exports for Flat Config today
- The plugin does not use the
configs.flat.*pattern (likeeslint-plugin-reactdoes). Instead, it has historically exposed flat-config presets under string keys such as:reactHooks.configs['recommended-latest'](noted as the flat-config entry point in the docs around v5.2.0) (app.unpkg.com)- In v6.x, the codebase introduced/uses a key like
reactHooks.configs['flat/recommended'](an array of flat config objects). (github.com)
Important v6.x nuance / bug report you’ll run into
- A reported problem in v6.1.0:
reactHooks.configs.recommendedcan be incompatible with ESLint flat config because it containsplugins: ['react-hooks'](array) instead of the required object form for flat config (plugins: { 'react-hooks': plugin }). (github.com)
“Release notes” signal for v6.0.0
- npm shows 6.0.0 was deprecated with the message: “published by accident, please use 6.0.0-rc.1 instead.” (npmjs.com)
Citations:
- 1: https://app.unpkg.com/eslint-plugin-react-hooks%400.0.0-experimental-223f81d8-20250707/files/README.md?utm_source=openai
- 2: Bug: eslint-plugin-react-hooks v.6.1.0 recommended config uses array instead of object react/react#34679
- 3: Bug: eslint-plugin-react-hooks v.6.1.0 recommended config uses array instead of object react/react#34679
- 4: https://www.npmjs.com/package/eslint-plugin-react-hooks/v/6.0.0?utm_source=openai
🌐 Web query:
eslint-plugin-react-hooks v7 new rules refs set-state-in-effect preserve-manual-memoization incompatible-library
💡 Result:
In eslint-plugin-react-hooks v7, the “new” items you’re seeing are mostly React Compiler–related lints that now ship in the plugin’s recommended presets (so they may appear “suddenly” after upgrading). The plugin’s recommended rule set includes (among others) refs, set-state-in-effect, preserve-manual-memoization, and incompatible-library. [1]
What the specific new rules mean
react-hooks/refs
Flags reading or writing ref.current during render (refs aren’t reactive; render should be pure). It infers “ref-ness” from useRef/createRef, names like *Ref accessing .current, or passing a value to a JSX ref prop. [2]
react-hooks/set-state-in-effect
Flags calling setState synchronously inside an Effect when it’s effectively “derived state” or otherwise causes an avoidable extra render pass (often you should compute during render instead of copying into state). [3]
react-hooks/preserve-manual-memoization
Ensures any existing manual memoization (useMemo, useCallback, React.memo) remains valid by requiring complete dependencies, because missing deps prevent the compiler from understanding the memoized computation’s data flow. [4]
react-hooks/incompatible-library
Flags usage patterns from known libraries/APIs that are incompatible with memoization assumptions (manual or compiler auto-memoization), so React Compiler can safely skip optimizing those components/hooks to avoid breaking behavior. [5]
Why this changed in v7
v7 simplified presets and made compiler-related rules enabled by default in the relevant presets (removing some older preset variants), which is why these warnings can appear after upgrading even if your code didn’t change. [6]
Sources:
[1] React docs: eslint-plugin-react-hooks rule list/presets (react.dev)
[2] React docs: refs lint (react.dev)
[3] React docs: set-state-in-effect lint (react.dev)
[4] React docs: preserve-manual-memoization lint (react.dev)
[5] React docs: incompatible-library lint (react.dev)
[6] v7 preset change summary (release notes excerpt) (scm.uninett.no)
Citations:
- 1: https://react.dev/reference/eslint-plugin-react-hooks?utm_source=openai
- 2: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs?utm_source=openai
- 3: https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect?utm_source=openai
- 4: https://react.dev/reference/eslint-plugin-react-hooks/lints/preserve-manual-memoization?utm_source=openai
- 5: https://react.dev/reference/eslint-plugin-react-hooks/lints/incompatible-library?utm_source=openai
- 6: https://scm.uninett.no/designsystem/sds-komponentbibliotek/-/merge_requests/1376?utm_source=openai
Fix the eslint-plugin-react-hooks config API path.
The configs.flat['recommended-latest'] path does not match eslint-plugin-react-hooks' actual API. The plugin does not expose a configs.flat object; it uses configs['recommended-latest'] or configs['flat/recommended'] instead. The four rules being disabled (refs, set-state-in-effect, preserve-manual-memoization, incompatible-library) are legitimate React Compiler-related lints, but the config reference needs correction to avoid potential runtime errors.
🤖 Prompt for AI Agents
In `@packages/tools/eslint-configs/react.js` around lines 60 - 69, The config
reference reactHooksPlugin.configs.flat['recommended-latest'] is invalid;
replace it with the plugin's actual API, e.g.,
reactHooksPlugin.configs['recommended-latest'] (or
reactHooksPlugin.configs['flat/recommended']) and keep the rules block that
disables 'react-hooks/refs', 'react-hooks/set-state-in-effect',
'react-hooks/preserve-manual-memoization', and
'react-hooks/incompatible-library' so the ESLint import uses a valid configs
property (update the reactHooksPlugin.configs[...] expression in the same object
where those rule names appear).
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In @.agents/code-style.md:
- Around line 15-16: Update the wording in the "File Extensions" bullet to
reference ES module resolution / Node 22+ instead of "Node 16 resolution":
change the phrase in the line starting with "**File Extensions:** MUST include
file extensions in imports to satisfy Node 16 resolution" to mention ES module
resolution or "Node 22+" (e.g., "to satisfy ES module resolution (Node 22+)")
and keep the example import unchanged; leave the "Aliases" bullet as-is.
In @.agents/testing.md:
- Around line 33-35: Update the testing guidelines to explicitly allow .tsx test
filenames alongside .ts by mentioning `.unit.test.tsx` and `.int.test.tsx` as
valid suffixes; adjust the examples that currently list `.unit.test.ts` and
`.int.test.ts` to include their `.tsx` counterparts and clarify that
component/React tests may use `.tsx` variants, and ensure references to test
helpers (`src/tests/` and `*.test-helper.ts`) note that helper files may also be
`.ts` or `.tsx` as appropriate.
In `@examples/blog-with-auth/apps/admin/.env.development`:
- Line 4: The DEV_BACKEND_HOST value was changed to use port 5001 (previously
3001) which looks out of scope for the linting/Prettier upgrade PR; either
document this port change in the PR description and update project docs (e.g.,
CLAUDE.md) explaining why DEV_BACKEND_HOST (and related port changes 3030→5030)
were updated, or revert the change in the admin .env.development back to the
original port (restore DEV_BACKEND_HOST to its prior port) so the PR only
contains linting/prettier updates.
In `@examples/blog-with-auth/apps/backend/src/services/config.ts`:
- Line 24: Default server port SERVER_PORT in config.ts is set to 5001 which may
conflict with macOS AirPlay Receiver; change the default to a less contentious
port (e.g., 5002 or 5050) by updating the
z.coerce.number().min(...).max(...).default(...) call for SERVER_PORT, and if
5001 was chosen intentionally, add a short comment or docs note explaining the
choice so developers are aware of the potential macOS conflict.
In `@examples/blog-with-auth/docker/docker-compose.yml`:
- Line 13: The docker-compose service is mapping the host Postgres port to 5432
via the POSTGRES_PORT default, which can conflict with a developer's local
PostgreSQL; update the default in the mapping from '${POSTGRES_PORT:-5432}' back
to the non-standard host port used previously (e.g. '${POSTGRES_PORT:-3432}') so
POSTGRES_PORT remains overrideable while avoiding local port collisions—look for
the POSTGRES_PORT entry in the docker-compose.yml service that defines the
Postgres port mapping to make this change.
🧹 Nitpick comments (1)
.agents/code-style.md (1)
5-6: Soften the “always use ?? instead of ||” rule to avoid behavioral changes.
||is sometimes intentionally used to fall back on falsy values (e.g., empty string or 0). Consider wording this as a preference with exceptions.♻️ Suggested wording tweak
-- **Nullish Coalescing:** Always use the nullish coalescing operator (`??`) instead of logical or (`||`) for safety. +- **Nullish Coalescing:** Prefer `??` over `||` when you only want to treat `null`/`undefined` as empty; allow `||` when falsy values like `0` or `""` should trigger fallback.
| - **File Extensions:** MUST include file extensions in imports to satisfy Node 16 resolution (e.g., `import ... from './utils.js'`). | ||
| - **Aliases:** Use absolute paths via import aliases where `#src/` is the alias for `src/`. |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check root-level Node version and TS config
echo "=== Checking root package.json for Node version ==="
if [ -f package.json ]; then
cat package.json | jq '.engines, .volta' 2>/dev/null || grep -i -A2 -B2 'engines\|node' package.json || true
fi
echo ""
echo "=== Checking for .nvmrc, .node-version, .tool-versions ==="
for file in .nvmrc .node-version .tool-versions; do
if [ -f "$file" ]; then
echo "File: $file"
cat "$file"
fi
done
echo ""
echo "=== Checking root tsconfig.json for module/moduleResolution ==="
if [ -f tsconfig.json ]; then
cat tsconfig.json | jq '.compilerOptions | {module, moduleResolution}' 2>/dev/null || grep -E 'module|moduleResolution' tsconfig.json || true
fi
echo ""
echo "=== Checking .agents/code-style.md full content ==="
if [ -f .agents/code-style.md ]; then
cat -n .agents/code-style.md
fiRepository: halfdomelabs/baseplate
Length of output: 4017
Update "Node 16 resolution" reference to reflect current Node 22 requirement.
Line 15 references "Node 16 resolution," but the repo is pinned to Node 22.18.0 (per package.json engines, .nvmrc, and .node-version). Update the wording to reference ES modules or Node 22+ to align with the actual runtime. File extensions are required for ES module resolution (which Node 22 uses), not a Node 16-specific requirement.
🤖 Prompt for AI Agents
In @.agents/code-style.md around lines 15 - 16, Update the wording in the "File
Extensions" bullet to reference ES module resolution / Node 22+ instead of "Node
16 resolution": change the phrase in the line starting with "**File
Extensions:** MUST include file extensions in imports to satisfy Node 16
resolution" to mention ES module resolution or "Node 22+" (e.g., "to satisfy ES
module resolution (Node 22+)") and keep the example import unchanged; leave the
"Aliases" bullet as-is.
| - **Unit Tests:** Colocate with source files using the `.unit.test.ts` suffix. | ||
| - **Integration Tests:** Use the `.int.test.ts` suffix. | ||
| - **Test Helpers:** Place shared setup code or utilities in `src/tests/` or create `*.test-helper.ts` files. |
There was a problem hiding this comment.
Clarify that .tsx test suffixes are valid too.
React/component tests often live in .unit.test.tsx / .int.test.tsx. The current wording only mentions .ts, which can mislead. Consider updating to explicitly include .tsx.
✏️ Suggested doc tweak
-- **Unit Tests:** Colocate with source files using the `.unit.test.ts` suffix.
-- **Integration Tests:** Use the `.int.test.ts` suffix.
+- **Unit Tests:** Colocate with source files using the `.unit.test.ts` or `.unit.test.tsx` suffix.
+- **Integration Tests:** Use the `.int.test.ts` or `.int.test.tsx` suffix.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - **Unit Tests:** Colocate with source files using the `.unit.test.ts` suffix. | |
| - **Integration Tests:** Use the `.int.test.ts` suffix. | |
| - **Test Helpers:** Place shared setup code or utilities in `src/tests/` or create `*.test-helper.ts` files. | |
| - **Unit Tests:** Colocate with source files using the `.unit.test.ts` or `.unit.test.tsx` suffix. | |
| - **Integration Tests:** Use the `.int.test.ts` or `.int.test.tsx` suffix. | |
| - **Test Helpers:** Place shared setup code or utilities in `src/tests/` or create `*.test-helper.ts` files. |
🤖 Prompt for AI Agents
In @.agents/testing.md around lines 33 - 35, Update the testing guidelines to
explicitly allow .tsx test filenames alongside .ts by mentioning
`.unit.test.tsx` and `.int.test.tsx` as valid suffixes; adjust the examples that
currently list `.unit.test.ts` and `.int.test.ts` to include their `.tsx`
counterparts and clarify that component/React tests may use `.tsx` variants, and
ensure references to test helpers (`src/tests/` and `*.test-helper.ts`) note
that helper files may also be `.ts` or `.tsx` as appropriate.
| VITE_GRAPH_API_ENDPOINT=/api/graphql | ||
| VITE_SENTRY_DSN= | ||
| DEV_BACKEND_HOST=http://localhost:3001 | ||
| DEV_BACKEND_HOST=http://localhost:5001 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Check the backend .env files for port configuration
fd -type f -name '.env*' 'examples/blog-with-auth/apps/backend' -x cat {}Repository: halfdomelabs/baseplate
Length of output: 236
🏁 Script executed:
# Also check the admin app's complete .env.development file
cat examples/blog-with-auth/apps/admin/.env.developmentRepository: halfdomelabs/baseplate
Length of output: 190
🏁 Script executed:
# Search for port references across the project to understand the configuration
rg "5001|5030" examples/blog-with-auth/ -A 2 -B 2Repository: halfdomelabs/baseplate
Length of output: 1128
🏁 Script executed:
# Check if there's any documentation about port configuration
find examples/blog-with-auth -type f \( -name "README*" -o -name "*.md" \) -exec grep -l "port\|5001\|5030" {} \;Repository: halfdomelabs/baseplate
Length of output: 99
🏁 Script executed:
# Check the CLAUDE.md documentation
cat examples/blog-with-auth/CLAUDE.mdRepository: halfdomelabs/baseplate
Length of output: 13402
🏁 Script executed:
# Check if there are any other backend .env configuration files
fd -e env 'examples/blog-with-auth/apps/backend' -x cat -n {}Repository: halfdomelabs/baseplate
Length of output: 515
🏁 Script executed:
# Look for any recent commits or PR context about port changes
cd examples/blog-with-auth && git log --oneline -20 | head -20Repository: halfdomelabs/baseplate
Length of output: 103
Document the port changes or confirm they belong in this PR.
The port changes are properly configured—the backend defaults to port 5001, and the admin app is correctly pointed to it. However, these port changes appear out of scope for a "Upgrade Linting / Prettier packages" PR and are not documented in the project's CLAUDE.md or recent git history.
Either document why the ports changed (3001→5001, 3030→5030) in the PR description/commit message, or if these changes are accidental, revert them to keep the PR focused on linting/prettier upgrades.
🧰 Tools
🪛 dotenv-linter (4.0.0)
[warning] 4-4: [UnorderedKey] The DEV_BACKEND_HOST key should go before the VITE_ENVIRONMENT key
(UnorderedKey)
🤖 Prompt for AI Agents
In `@examples/blog-with-auth/apps/admin/.env.development` at line 4, The
DEV_BACKEND_HOST value was changed to use port 5001 (previously 3001) which
looks out of scope for the linting/Prettier upgrade PR; either document this
port change in the PR description and update project docs (e.g., CLAUDE.md)
explaining why DEV_BACKEND_HOST (and related port changes 3030→5030) were
updated, or revert the change in the admin .env.development back to the original
port (restore DEV_BACKEND_HOST to its prior port) so the PR only contains
linting/prettier updates.
| SERVER_HOST: z.string().default('localhost'), | ||
| // Port to bind the server to | ||
| SERVER_PORT: z.coerce.number().min(1).max(65_535).default(3001), | ||
| SERVER_PORT: z.coerce.number().min(1).max(65_535).default(5001), |
There was a problem hiding this comment.
Port 5001 may conflict with macOS AirPlay Receiver.
On macOS Monterey and later, port 5001 is used by AirPlay Receiver by default, which can cause binding failures during local development. If this was changed to avoid a conflict with another service, consider documenting it or choosing a less contentious port (e.g., 5002 or 5050).
🤖 Prompt for AI Agents
In `@examples/blog-with-auth/apps/backend/src/services/config.ts` at line 24,
Default server port SERVER_PORT in config.ts is set to 5001 which may conflict
with macOS AirPlay Receiver; change the default to a less contentious port
(e.g., 5002 or 5050) by updating the
z.coerce.number().min(...).max(...).default(...) call for SERVER_PORT, and if
5001 was chosen intentionally, add a short comment or docs note explaining the
choice so developers are aware of the potential macOS conflict.
| POSTGRES_INITDB_ARGS: '--encoding=UTF8 --locale=en_US.utf8' | ||
| ports: | ||
| - '${POSTGRES_PORT:-3432}:5432' | ||
| - '${POSTGRES_PORT:-5432}:5432' |
There was a problem hiding this comment.
Default host port 5432 may conflict with a local PostgreSQL instance.
The previous default of 3432 avoided clashes with a locally installed PostgreSQL. Switching to 5432 means developers with a local PostgreSQL running will hit a port conflict out of the box. Since the env var override exists this isn't blocking, but consider whether the non-standard default was intentional.
🤖 Prompt for AI Agents
In `@examples/blog-with-auth/docker/docker-compose.yml` at line 13, The
docker-compose service is mapping the host Postgres port to 5432 via the
POSTGRES_PORT default, which can conflict with a developer's local PostgreSQL;
update the default in the mapping from '${POSTGRES_PORT:-5432}' back to the
non-standard host port used previously (e.g. '${POSTGRES_PORT:-3432}') so
POSTGRES_PORT remains overrideable while avoiding local port collisions—look for
the POSTGRES_PORT entry in the docker-compose.yml service that defines the
Postgres port mapping to make this change.
Summary by CodeRabbit
New Features
Bug Fixes
Chores
Refactor
Documentation