feat: add support for biome for linting/formatting#172
feat: add support for biome for linting/formatting#172
Conversation
📝 WalkthroughWalkthroughAdd a pluggable lint backend abstraction (eslint | biome), implement EslintBackend and BiomeBackend, propagate backend selection through TypeScript builders, nx-monorepo, and lint-staged flows, and adjust config emission and task wiring for Biome-enabled projects. Changes
Sequence Diagram(s)sequenceDiagram
participant Dev as Developer
participant Project as Project/Builders
participant LintConfig as LintConfig
participant Backend as LintBackend (Eslint / Biome)
participant Tasks as Tasks / nx / lint-staged
Dev->>Project: configure project with lint backend option
Project->>LintConfig: LintConfig.of(project) / instantiate with backend
LintConfig->>Backend: initialize selected backend
Backend->>LintConfig: provide exec/format command, task-updater, pre-synth hooks
LintConfig->>Tasks: update lint task steps / emit backend-specific config files
Tasks->>Backend: run lint/format during lint-staged, test, nx runs
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 4/5 reviews remaining, refill in 12 minutes. Comment |
|
View your CI Pipeline Execution ↗ for commit 1abd59d
☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/projen/component/linting/src/linting.ts (1)
50-62:⚠️ Potential issue | 🔴 Critical
FormatRequestleaks a non-exported type into the public API.Line 62 exposes
LintBackendfrom an exported interface, butLintBackendis not exported (abstract class defined at line 80). This breaks TypeScript declaration emit and external callers cannot legally provide thelinterfield. Movelinterto an internal request type, or export a publicLintBackendinterface instead.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/projen/component/linting/src/linting.ts` around lines 50 - 62, The exported interface FormatRequest currently references a non-exported type LintBackend which leaks an internal type into the public API; update the code so the public API is valid by either (A) making LintBackend public (export the abstract class or expose a public interface named LintBackend) and keeping the linter?: LintBackend field on FormatRequest, or (B) remove the linter field from the exported FormatRequest and create an internal request type (e.g., InternalFormatRequest or FormatRequestInternal) that includes linter?: LintBackend for internal use; locate the declarations of FormatRequest and LintBackend in linting.ts and apply one of these two changes so TypeScript declaration emit no longer references an unexported type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/projen/component/linting/src/linting.ts`:
- Around line 212-228: The current logic builds extendsPath and always sets
biomeConfig.extends to [extendsPath], which causes a project to extend itself
when findRootProject(project) === project; update the code that builds
leafOptions (used to construct Biome in new Biome(project, leafOptions)) to only
add extendsPath into biomeConfig.extends when findRootProject(project) !==
project (or when rootRelative !== '.'), otherwise leave extends empty or omit
the extends property; also consider coordinating with maybeEmitRootBiomeConfig
to ensure a separate root config is only referenced when it will actually be
emitted.
In `@packages/projen/project/typescript/src/builders.ts`:
- Around line 293-301: The YAML pre-commit hook in applyLintStaged
unconditionally runs "prettier --write" causing failures when
lintConfig?.backend === 'biome' and prettier is disabled; update the YAML entry
to follow the TS/JS pattern (check lintConfig?.backend === 'biome') and
conditionally use the biome formatter command (or skip adding a prettier
command) when the backend is 'biome' so the YAML hook either runs the biome
formatting command or is omitted, mirroring the conditional logic used in the
TS/JS handlers inside applyLintStaged.
---
Outside diff comments:
In `@packages/projen/component/linting/src/linting.ts`:
- Around line 50-62: The exported interface FormatRequest currently references a
non-exported type LintBackend which leaks an internal type into the public API;
update the code so the public API is valid by either (A) making LintBackend
public (export the abstract class or expose a public interface named
LintBackend) and keeping the linter?: LintBackend field on FormatRequest, or (B)
remove the linter field from the exported FormatRequest and create an internal
request type (e.g., InternalFormatRequest or FormatRequestInternal) that
includes linter?: LintBackend for internal use; locate the declarations of
FormatRequest and LintBackend in linting.ts and apply one of these two changes
so TypeScript declaration emit no longer references an unexported type.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 785dd8e5-8030-4d2c-b866-ca636c56d291
📒 Files selected for processing (4)
packages/projen/component/linting/src/linting.tspackages/projen/project/nx-monorepo/src/nx-monorepo.tspackages/projen/project/typescript/src/builders.tsprojenrc/monorepo.ts
9553e96 to
c2b77dd
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (2)
packages/projen/component/linting/src/linting.ts (1)
212-225:⚠️ Potential issue | 🔴 CriticalDon't make a root
biome.jsoncextend itself.When
findRootProject(project) === project, this buildsextends: ['./biome.jsonc']withroot: false. That makes standalone Biome projects—and monorepo roots that opt into Biome directly—generate a self-referential config.maybeEmitRootBiomeConfig()does not fix that case because it only emits a separate root config for projects with children.This needs a root-project branch that omits
extendsand marks the config as root instead.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/projen/component/linting/src/linting.ts` around lines 212 - 225, The code currently sets extendsPath and builds leafOptions.biomeConfig with extends even when findRootProject(project) === project, causing self-referential configs; update the branch where root equals project to instead omit the extends property and set biomeConfig.root = true (e.g., when root === project, construct leafOptions.biomeConfig without extends and with root: true), otherwise keep the existing extendsPath and root: false behavior; touch the logic that builds leafOptions (and any use in maybeEmitRootBiomeConfig) to ensure root projects do not include extends ['./biome.jsonc'] or root: false.packages/projen/project/typescript/src/builders.ts (1)
386-393:⚠️ Potential issue | 🟠 MajorDon't invoke Prettier unconditionally in biome mode.
TypescriptLintingBuilder.applyOptions()turnsprettieroff whenbiomeis enabled, but this YAML entry still always emitsprettier --write. In a Biome-backed project, lint-staged can now call a binary that is no longer installed.Possible fix
- { - extensions: [ExtensionMatch.YAML], - commands: [ - NodePackageUtils.command.exec( - project.package.packageManager, - this.prettierCmd, - ), - ], - }, + ...(lintConfig?.backend === 'biome' + ? [] + : [ + { + extensions: [ExtensionMatch.YAML], + commands: [ + NodePackageUtils.command.exec( + project.package.packageManager, + this.prettierCmd, + ), + ], + }, + ]),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/projen/project/typescript/src/builders.ts` around lines 386 - 393, The YAML lint-staged entry currently always emits the Prettier command (this.prettierCmd) even when Biome is enabled; update the code that builds the YAML commands (the block producing the extensions/commands array) to include the NodePackageUtils.command.exec(project.package.packageManager, this.prettierCmd) entry only when Prettier is actually enabled (use the same condition/flag used by TypescriptLintingBuilder.applyOptions(), e.g., check this.prettierCmd or the builder's prettier-enabled flag) so that Biome-backed projects do not reference a missing Prettier binary.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@packages/projen/component/linting/src/linting.ts`:
- Around line 212-225: The code currently sets extendsPath and builds
leafOptions.biomeConfig with extends even when findRootProject(project) ===
project, causing self-referential configs; update the branch where root equals
project to instead omit the extends property and set biomeConfig.root = true
(e.g., when root === project, construct leafOptions.biomeConfig without extends
and with root: true), otherwise keep the existing extendsPath and root: false
behavior; touch the logic that builds leafOptions (and any use in
maybeEmitRootBiomeConfig) to ensure root projects do not include extends
['./biome.jsonc'] or root: false.
In `@packages/projen/project/typescript/src/builders.ts`:
- Around line 386-393: The YAML lint-staged entry currently always emits the
Prettier command (this.prettierCmd) even when Biome is enabled; update the code
that builds the YAML commands (the block producing the extensions/commands
array) to include the
NodePackageUtils.command.exec(project.package.packageManager, this.prettierCmd)
entry only when Prettier is actually enabled (use the same condition/flag used
by TypescriptLintingBuilder.applyOptions(), e.g., check this.prettierCmd or the
builder's prettier-enabled flag) so that Biome-backed projects do not reference
a missing Prettier binary.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a7f670c8-bb9d-405c-b763-29781172a031
📒 Files selected for processing (4)
packages/projen/component/linting/src/linting.tspackages/projen/project/nx-monorepo/src/nx-monorepo.tspackages/projen/project/typescript/src/builders.tsprojenrc/monorepo.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- projenrc/monorepo.ts
283636f to
fd22b45
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/projen/component/linting/src/linting.ts (2)
488-500: Type coercions bypass Biome config validation.The
as nevercasts work around projen's Biome config typing, but suppress compile-time validation. If the Biome config schema changes upstream, these won't catch type errors.Consider using string literal types or the actual enum values if projen exposes them.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/projen/component/linting/src/linting.ts` around lines 488 - 500, The Biome config is using "as never" casts (see biomeConfig -> formatter.indentStyle and javascript.formatter.quoteStyle/semicolons in linting.ts), which bypasses compile-time validation; replace these casts with the correct literal types or the exported enum/union types from projen/biome (import the appropriate enum or type and use e.g. the enum value or a string literal that matches the declared type) so the TypeScript compiler enforces the Biome schema instead of silencing errors with "as never".
187-191: Consider defensive checks for task existence.The non-null assertions assume the
eslinttask exists with an executable step. While this should hold whenEslintBackendis properly instantiated, a guard would prevent cryptic runtime errors if the task is missing or modified.♻️ Suggested defensive check
setLintExec(exec: string, replace: string = 'eslint'): void { - const task = this.project.tasks.tryFind('eslint')! - const cmd = task.steps[0].exec!.replace(replace, exec) - replaceTask(this.project, 'eslint', [{ exec: cmd }]) + const task = this.project.tasks.tryFind('eslint') + const existingExec = task?.steps[0]?.exec + if (!existingExec) { + this.project.logger.warn('eslint task not found or missing exec step') + return + } + const cmd = existingExec.replace(replace, exec) + replaceTask(this.project, 'eslint', [{ exec: cmd }]) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/projen/component/linting/src/linting.ts` around lines 187 - 191, The method setLintExec uses non-null assertions on the result of this.project.tasks.tryFind('eslint') and on task.steps[0].exec, which can produce cryptic runtime errors if the eslint task or its steps are missing; add defensive checks in setLintExec to verify the task exists and that task.steps and task.steps[0].exec are defined before proceeding (e.g., if (!task || !task.steps?.[0]?.exec) throw or return a clear error), then safely compute cmd and call replaceTask(this.project, 'eslint', [{ exec: cmd }]); ensure you remove the non-null assertions and surface a descriptive message mentioning setLintExec and the eslint task when failing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/projen/component/linting/src/linting.ts`:
- Around line 488-500: The Biome config is using "as never" casts (see
biomeConfig -> formatter.indentStyle and
javascript.formatter.quoteStyle/semicolons in linting.ts), which bypasses
compile-time validation; replace these casts with the correct literal types or
the exported enum/union types from projen/biome (import the appropriate enum or
type and use e.g. the enum value or a string literal that matches the declared
type) so the TypeScript compiler enforces the Biome schema instead of silencing
errors with "as never".
- Around line 187-191: The method setLintExec uses non-null assertions on the
result of this.project.tasks.tryFind('eslint') and on task.steps[0].exec, which
can produce cryptic runtime errors if the eslint task or its steps are missing;
add defensive checks in setLintExec to verify the task exists and that
task.steps and task.steps[0].exec are defined before proceeding (e.g., if (!task
|| !task.steps?.[0]?.exec) throw or return a clear error), then safely compute
cmd and call replaceTask(this.project, 'eslint', [{ exec: cmd }]); ensure you
remove the non-null assertions and surface a descriptive message mentioning
setLintExec and the eslint task when failing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6e12052e-3435-4912-aad3-a42adea9db21
📒 Files selected for processing (5)
packages/projen/component/linting/src/linting.tspackages/projen/component/vue/src/vue.tspackages/projen/project/nx-monorepo/src/nx-monorepo.tspackages/projen/project/typescript/src/builders.tsprojenrc/monorepo.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/projen/component/vue/src/vue.ts
- projenrc/monorepo.ts
…int backend, implement biome backend Signed-off-by: Braden Mars <[email protected]>
…, hooks builder Signed-off-by: Braden Mars <[email protected]>
…roject has it Signed-off-by: Braden Mars <[email protected]>
Signed-off-by: Braden Mars <[email protected]>
…en linting files Signed-off-by: Braden Mars <[email protected]>
Signed-off-by: Braden Mars <[email protected]>
Signed-off-by: Braden Mars <[email protected]>
Signed-off-by: Braden Mars <[email protected]>
…g biome Signed-off-by: Braden Mars <[email protected]>
fd22b45 to
cf285dc
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
projenrc/monorepo.ts (1)
84-106:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMake the YAML lint-staged command backend-aware too.
This block switches TS/JS to Biome, but the YAML entry still hard-codes
prettier --write. For subprojects created withTypescriptLintingBuilderin Biome mode, Prettier is explicitly turned off, so a staged YAML file will still break pre-commit. This needs the sameuseBiome ? biomeCmd : prettierCmdsplit that already exists inpackages/projen/project/typescript/src/builders.ts.Suggested fix
const lintConfig = LintConfig.of(project) + const useBiome = lintConfig?.backend === 'biome' const tsCmd = - lintConfig?.backend === 'biome' + useBiome ? 'biome check --files-ignore-unknown=true --no-errors-on-unmatched --write' : 'eslint --no-error-on-unmatched-pattern --fix' + const yamlCmd = useBiome + ? 'biome check --files-ignore-unknown=true --no-errors-on-unmatched --write' + : 'prettier --write' new LintStaged(project, { entries: [ { @@ { extensions: [ExtensionMatch.YAML], commands: [ NodePackageUtils.command.exec( this.package.packageManager, - 'prettier --write', + yamlCmd, ), ], },🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@projenrc/monorepo.ts` around lines 84 - 106, The YAML lint-staged entry hard-codes "prettier --write" which breaks Biome-only projects; mirror the TS/JS logic: obtain lintConfig via LintConfig.of(project) and compute a yamlCmd similar to tsCmd (e.g., use the Biome formatting command when lintConfig?.backend === 'biome', otherwise "prettier --write"), then replace the hard-coded string in the LintStaged entries (the YAML entry under new LintStaged(...), where NodePackageUtils.command.exec(this.package.packageManager, 'prettier --write') is used) with NodePackageUtils.command.exec(this.package.packageManager, yamlCmd) so YAML uses the backend-aware formatter.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/projen/component/linting/src/linting.ts`:
- Around line 211-226: The root/standalone Biome config path (in BiomeBackend
where leafOptions and the isRoot branch are built) is missing the repo
formatting defaults (tabs, singleQuote, asNeeded) that maybeEmitRootBiomeConfig
emits, causing root/standalone projects to fall back to Biome defaults; fix by
extracting the repo formatting defaults into a shared helper (e.g.,
getRepoFormattingDefaults or reusing maybeEmitRootBiomeConfig logic) and merge
those defaults into the biomeConfig for the isRoot branch when constructing
leafOptions (referencing leafOptions, biomeConfig, isRoot, and
maybeEmitRootBiomeConfig/BiomeBackend) so both the root and the separate
emission path use the same formatting defaults.
- Around line 65-78: The shared linting component is removing Biome from every
NodeProject's testTask via removeBiomeFromTestTask(project, biome), which breaks
standalone consumers; change this to be opt-in or relocated to Nx-specific
integration: add an explicit boolean option (e.g. removeBiomeFromTestTask =
false) to the linting component's options and only call removeBiomeFromTestTask
if that option is true (or alternatively move the call into the Nx integration
code path that knows the Nx target exists); update the linting component
constructor and all call sites that create Biome to pass the option (or enable
it from the Nx integrator) so standalone NodeProject/biome users keep linting in
pnpm test.
---
Duplicate comments:
In `@projenrc/monorepo.ts`:
- Around line 84-106: The YAML lint-staged entry hard-codes "prettier --write"
which breaks Biome-only projects; mirror the TS/JS logic: obtain lintConfig via
LintConfig.of(project) and compute a yamlCmd similar to tsCmd (e.g., use the
Biome formatting command when lintConfig?.backend === 'biome', otherwise
"prettier --write"), then replace the hard-coded string in the LintStaged
entries (the YAML entry under new LintStaged(...), where
NodePackageUtils.command.exec(this.package.packageManager, 'prettier --write')
is used) with NodePackageUtils.command.exec(this.package.packageManager,
yamlCmd) so YAML uses the backend-aware formatter.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: eea4179d-33c2-4fe8-8222-4f83b1cf101a
📒 Files selected for processing (5)
packages/projen/component/linting/src/linting.tspackages/projen/component/vue/src/vue.tspackages/projen/project/nx-monorepo/src/nx-monorepo.tspackages/projen/project/typescript/src/builders.tsprojenrc/monorepo.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/projen/project/nx-monorepo/src/nx-monorepo.ts
…task opt-in Signed-off-by: Braden Mars <[email protected]>
…to true Signed-off-by: Braden Mars <[email protected]>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/projen/component/linting/src/linting.ts (1)
59-71:⚠️ Potential issue | 🔴 CriticalExported
FormatRequestleaks a private type.
FormatRequest.linteris typed asLintBackend, butLintBackendis not exported. Sincesrc/index.tsre-exports all exports from this module,FormatRequestbecomes part of the public API. TypeScript declaration emit will fail because it cannot resolve theLintBackendtype for external consumers. Either makeFormatRequestinternal or export a public formatter interface instead of the concrete backend base class.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/projen/component/linting/src/linting.ts` around lines 59 - 71, FormatRequest currently exposes a non-exported type via its optional linter property (LintBackend), causing declaration emit failures; fix by replacing the private type with a public contract or hiding the type: either export a public interface (e.g., name it Formatter or ILintBackend) that describes the methods/properties needed and use that public interface as the type for FormatRequest.linter, or mark FormatRequest as internal (remove its export) so it is not re-exported by src/index.ts; update usages of LintBackend in this module to use the new exported interface (or adjust callers if FormatRequest is made internal) and ensure src/index.ts no longer re-exports the private type.
♻️ Duplicate comments (2)
packages/projen/project/typescript/src/builders.ts (1)
312-318:⚠️ Potential issue | 🟠 Major | ⚡ Quick winDon't force
removeBiomeFromTestTaskfor every TypeScript Biome project.This overrides the linting component's opt-in default for all callers, so standalone TypeScript projects lose Biome from
pnpm testas soon as they switch backends. This should stay caller-controlled or be enabled only from the Nx-specific integration that provides the replacement target.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/projen/project/typescript/src/builders.ts` around lines 312 - 318, The code is forcing removeBiomeFromTestTask: true when constructing the LintConfig for Biome (in builders.ts inside the TypeScript project builder), which overrides callers' defaults; remove that hardcoded property so the flag is caller-controlled (either omit removeBiomeFromTestTask entirely from the object so LintConfig uses its opt-in default or pass through this.options.removeBiomeFromTestTask). If the behavior should only be enabled for the Nx integration, set removeBiomeFromTestTask only in the Nx-specific integration code (not here) when creating the LintConfig for Nx projects.packages/projen/component/linting/src/linting.ts (1)
520-545:⚠️ Potential issue | 🟠 Major | ⚡ Quick winRoot biome emission still strips Biome from
pnpm testunconditionally.
maybeEmitRootBiomeConfig()always callsremoveBiomeFromTestTask()for the generated root Biome task. That bypasses the new opt-in flag and means a monorepo root stops running Biome inpnpm testas soon as any child opts into the Biome backend.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/projen/component/linting/src/linting.ts` around lines 520 - 545, maybeEmitRootBiomeConfig currently always calls removeBiomeFromTestTask(rootBiomeProject, rootBiome) which unconditionally strips Biome from the root pnpm test; change this by guarding that call with the repo/monorepo opt-in flag (the same flag used to decide whether to emit/enable root Biome for children) so removeBiomeFromTestTask is only invoked when the opt-in behavior requires removing root Biome from test runs. Locate maybeEmitRootBiomeConfig and wrap the removeBiomeFromTestTask(...) call in a conditional that checks the existing opt-in property/config used for child Biome opting, or add a boolean check exposed by the same configuration path, so the root Biome is left in pnpm test unless opt-in dictates removal.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/projen/project/typescript/src/builders.ts`:
- Around line 280-304: The builder currently only checks typed.biome in
applyOptions so specifying backend: 'biome' via applyProject
(this.options.backend) doesn't disable Projen's native lint stack; update
applyOptions to consider both typed.biome and options.backend === 'biome' when
setting this.useBiome and this.biomeOptions, and ensure the returned options
object (when enabling Biome) always sets biome: false, eslint: false, prettier:
false to prevent Projen wiring; also review applyProject to ensure it doesn't
override this.useBiome or this.biomeOptions set here.
---
Outside diff comments:
In `@packages/projen/component/linting/src/linting.ts`:
- Around line 59-71: FormatRequest currently exposes a non-exported type via its
optional linter property (LintBackend), causing declaration emit failures; fix
by replacing the private type with a public contract or hiding the type: either
export a public interface (e.g., name it Formatter or ILintBackend) that
describes the methods/properties needed and use that public interface as the
type for FormatRequest.linter, or mark FormatRequest as internal (remove its
export) so it is not re-exported by src/index.ts; update usages of LintBackend
in this module to use the new exported interface (or adjust callers if
FormatRequest is made internal) and ensure src/index.ts no longer re-exports the
private type.
---
Duplicate comments:
In `@packages/projen/component/linting/src/linting.ts`:
- Around line 520-545: maybeEmitRootBiomeConfig currently always calls
removeBiomeFromTestTask(rootBiomeProject, rootBiome) which unconditionally
strips Biome from the root pnpm test; change this by guarding that call with the
repo/monorepo opt-in flag (the same flag used to decide whether to emit/enable
root Biome for children) so removeBiomeFromTestTask is only invoked when the
opt-in behavior requires removing root Biome from test runs. Locate
maybeEmitRootBiomeConfig and wrap the removeBiomeFromTestTask(...) call in a
conditional that checks the existing opt-in property/config used for child Biome
opting, or add a boolean check exposed by the same configuration path, so the
root Biome is left in pnpm test unless opt-in dictates removal.
In `@packages/projen/project/typescript/src/builders.ts`:
- Around line 312-318: The code is forcing removeBiomeFromTestTask: true when
constructing the LintConfig for Biome (in builders.ts inside the TypeScript
project builder), which overrides callers' defaults; remove that hardcoded
property so the flag is caller-controlled (either omit removeBiomeFromTestTask
entirely from the object so LintConfig uses its opt-in default or pass through
this.options.removeBiomeFromTestTask). If the behavior should only be enabled
for the Nx integration, set removeBiomeFromTestTask only in the Nx-specific
integration code (not here) when creating the LintConfig for Nx projects.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 62ecc697-d351-4b92-be71-14d81813b7b6
📒 Files selected for processing (2)
packages/projen/component/linting/src/linting.tspackages/projen/project/typescript/src/builders.ts
| applyOptions( | ||
| options: ProjectOptions & this['_outputOptions'], | ||
| ): ProjectOptions & this['_outputOptions'] { | ||
| const typed = options as ProjectOptions & | ||
| this['_outputOptions'] & { | ||
| biome?: boolean | ||
| biomeOptions?: javascript.BiomeOptions | ||
| eslint?: boolean | ||
| prettier?: boolean | ||
| } | ||
| // Always reset instance state — this builder is shared across projects. | ||
| this.useBiome = !!typed.biome | ||
| this.biomeOptions = typed.biomeOptions | ||
| if (this.useBiome) { | ||
| // Take over linting: skip Projen's native biome/eslint/prettier wiring | ||
| // so LintConfig can manage a single tool end-to-end. | ||
| return { | ||
| ...options, | ||
| biome: false, | ||
| eslint: false, | ||
| prettier: false, | ||
| } | ||
| } | ||
| return options | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Builder-level backend: 'biome' never disables the native lint stack.
applyOptions() only keys off typed.biome, but applyProject() also accepts this.options.backend === 'biome'. A caller using new TypescriptLintingBuilder({ backend: 'biome' }) will get a Biome LintConfig without turning off Projen's native eslint/prettier wiring, so both stacks can be configured at once.
Proposed fix
- this.useBiome = !!typed.biome
- this.biomeOptions = typed.biomeOptions
+ this.useBiome = !!typed.biome || this.options?.backend === 'biome'
+ this.biomeOptions = typed.biomeOptions ?? this.options?.biomeOptions🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/projen/project/typescript/src/builders.ts` around lines 280 - 304,
The builder currently only checks typed.biome in applyOptions so specifying
backend: 'biome' via applyProject (this.options.backend) doesn't disable
Projen's native lint stack; update applyOptions to consider both typed.biome and
options.backend === 'biome' when setting this.useBiome and this.biomeOptions,
and ensure the returned options object (when enabling Biome) always sets biome:
false, eslint: false, prettier: false to prevent Projen wiring; also review
applyProject to ensure it doesn't override this.useBiome or this.biomeOptions
set here.
Summary by CodeRabbit
New Features
Bug Fixes