Skip to content

Promotes the current **develop** line to **main**, including security-focused dependency work, test-sandbox alignment, packaged postinstall fix, Next.js dev Webpack fallback, and release **0.17.0-beta.1** (via chore(release) on develop). - #117

Merged
sergak01 merged 5 commits into
mainfrom
develop
Apr 6, 2026

Conversation

@sergak01

@sergak01 sergak01 commented Apr 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Promotes the current develop line to main, including security-focused dependency work, test-sandbox alignment, packaged postinstall fix, Next.js dev Webpack fallback, and release 0.17.0-beta.1 (via chore(release) on develop).

Primary integration: PR #116 (pp-3181).

What ships

Security and npm audit

  • Root overrides for transitive advisories (@xmldom/xmldom, brace-expansion, serialize-javascript, npm, file-type v22, etc.).
  • postinstall patch script for nested npm bundle copies; script is included in published files so tarball installs do not fail with a missing module.
  • Test apps under tests/ use matching overrides and refreshed lockfiles for clean npm audit in sandboxes.

Dependency and toolchain

  • TypeScript 6, Vitest/Playwright bumps, file-type 22, jsdom 28.0.0 (Vitest compatibility), esbuild ^0.27.7 (Vite 8 peers), Next 16.2.x, and related updates in root and test projects.

Next.js CLI (pp-dev next)

  • Webpack fallback when Turbopack fails due to unavailable native SWC bindings (e.g. Windows WDAC).
  • --webpack / --turbopack, PP_DEV_NEXT_WEBPACK, and TURBOPACK reset between attempts.
  • customServer: true on Next server options.

Version

  • 0.17.0-beta.1 — see chore(release): 0.17.0-beta.1 [skip ci] on develop.

Commit range (high level)

Summary by CodeRabbit

  • New Features

    • Added --webpack and --turbopack CLI flags for explicit bundler selection.
    • Implemented Webpack fallback when Turbopack native SWC initialization fails.
  • Bug Fixes

    • Fixed sandbox overrides test configuration.
  • Chores

    • Updated dependencies to latest stable versions.
    • Released version 0.17.0-beta.1.
    • Added automated vulnerability patching on installation.

sergak01 and others added 5 commits April 6, 2026 09:03
- Extend test-commonjs, test-nextjs, and test-nextjs-cjs overrides for xmldom,
  brace-expansion, lodash, path-to-regexp, picomatch, serialize-javascript, yaml.
- Point test-nextjs-cjs vite/esbuild overrides at current major lines.
- Refresh nested lockfiles; include root security postinstall and overrides.
- Retry prepare() with webpack: true when Turbopack errors match missing native
  bindings (e.g. Windows Application Control blocking @next/swc).
- Clear process.env.TURBOPACK between attempts so Webpack is not skipped.
- Add --webpack and --turbopack; support PP_DEV_NEXT_WEBPACK for scripts/CI.
- Set customServer: true explicitly on the Next custom server options.
- Bump root dependencies (TypeScript 6, file-type 22, Vitest/Playwright, etc.);
  pin jsdom to 28.0.0 and esbuild to ^0.27.7 for toolchain compatibility.
- Ship scripts/patch-npm-bundled-vulnerabilities.mjs in npm files so reinstall works.
- Refresh test-commonjs, test-nextjs, and test-nextjs-cjs lockfiles and overrides.
PP-3181 Hardens dependency security (root and test sandboxes), upgrades toolchain packages, fixes packaged installs that run `postinstall`, and makes `pp-dev next` resilient when Next.js Turbopack cannot use native SWC (e.g. Windows Application Control).
# [0.17.0-beta.1](v0.16.1...v0.17.0-beta.1) (2026-04-06)

### Bug Fixes

* **tests:** align sandbox overrides with audited dependency policy ([5841aa8](5841aa8))

### Features

* **cli:** Webpack fallback for Next dev when Turbopack native SWC fails ([5940f31](5940f31))
@coderabbitai

coderabbitai Bot commented Apr 6, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR introduces version 0.17.0-beta.1 with a Webpack fallback mechanism for Next.js dev server when Turbopack native SWC fails. It adds a postinstall script to patch npm bundled vulnerabilities, updates multiple dependencies and dependency overrides across the project, and adjusts TypeScript configuration in test environments.

Changes

Cohort / File(s) Summary
Release Documentation
CHANGELOG.md
Added release notes for version 0.17.0-beta.1 documenting Webpack fallback feature and sandbox overrides test fix.
Dependency Management & Vulnerability Patching
package.json, scripts/patch-npm-bundled-vulnerabilities.mjs
Bumped version to 0.17.0-beta.1, added postinstall script to patch npm bundled vulnerabilities, updated dependencies (axios, esbuild, file-type, rollup, sass, typescript, vite) and devDependencies (@playwright/test, @types/*, next, vitest, rollup-plugin-dts), expanded overrides for security remediation including @xmldom/xmldom, brace-expansion, file-type, npm, and serialize-javascript.
CLI Bundler Selection Logic
src/cli.ts
Introduced Webpack/Turbopack CLI flags and --webpack / --turbopack options; added parseNextBundlerCli() for bundler selection from CLI flags and environment variables; implemented isNextTurbopackNativeBindingsError() to detect native binding failures and fallback to Webpack; refactored Next.js app initialization into createAndPrepareNext() with error recovery and environment variable management.
Test Configuration Updates
tests/test-commonjs/package.json, tests/test-nextjs-cjs/package.json, tests/test-nextjs/package.json, tests/test-nextjs-cjs/tsconfig.json
Updated dependencies (typescript ^6.0.2, vite ^8.0.3, next ^16.2.2, file-type ^22.0.0) and expanded dependency overrides across test environments for vulnerability patching; changed moduleResolution from bundler to node in CommonJS test configuration.

Sequence Diagram(s)

sequenceDiagram
    participant User as User/CLI
    participant Parser as CLI Parser
    participant Turbopack as Turbopack<br/>Initialization
    participant Detector as Error Detector
    participant Webpack as Webpack<br/>Initialization
    participant Next as Next.js App

    User->>Parser: Invoke dev command<br/>(±--webpack/--turbopack flag)
    Parser->>Parser: parseNextBundlerCli()<br/>(check flags & env vars)
    
    alt Webpack explicitly requested
        Parser->>Webpack: Initialize with Webpack
        Webpack->>Next: Setup Next.js
    else Turbopack requested or auto
        Parser->>Turbopack: Attempt Turbopack<br/>initialization
        Turbopack-->>Detector: Native bindings error?
        
        alt Native binding error detected
            Detector->>Webpack: Fallback to Webpack
            Webpack->>Next: Setup Next.js
        else Success
            Turbopack->>Next: Setup Next.js
        end
    end
    
    Next-->>User: Dev server ready
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • MaksymovVolodymyr
  • michailozdemir
  • Sadilenko

Poem

🐰 Hops of bundlers, swift and fleet,
Webpack catching Turbopack's beat,
When native bindings break and fall,
Our fuzzy fallback saves them all!
Patches bundled, versions bright,
Zero-point-seventeen takes flight! 🚀

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately captures the main purpose: promoting develop to main with release 0.17.0-beta.1, including security work, postinstall fixes, and Webpack fallback.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CHANGELOG.md`:
- Around line 1-11: The release header uses a single '#' which triggers MD001
and skips a proper top-level release grouping; change the header for the release
"[0.17.0-beta.1]" from '#' to '##' and add or expand a short "Highlights" or
"Compatibility" subsection (under that release) calling out the
dependency/toolchain compatibility changes (e.g., Turbopack/SWC fallback
behavior) and the packaged security patch, and include a brief "Breaking Changes
/ Compatibility" note if any; update the existing "Bug Fixes" and "Features"
entries (5841aa8, 5940f31) to include one-line technical details so the
changelog matches the shipped contents and satisfies the markdownlint and PR
message guidelines.

In `@scripts/patch-npm-bundled-vulnerabilities.mjs`:
- Around line 13-19: The replaceDir helper currently performs rmSync and cpSync
which can throw and abort consumers' installs; modify replaceDir (the function
named replaceDir) to wrap the filesystem mutation calls (rmSync and cpSync) in a
try/catch block so any exceptions are caught, and on error emit a non-fatal
warning (e.g., console.warn or the module's logger) with contextual info
including src, dest and the caught error; retain the existing existsSync checks
(src and dirname(dest)) before attempting mutations and return early as now, but
ensure failures during rmSync/cpSync do not rethrow.

In `@src/cli.ts`:
- Around line 763-767: The assetPrefix should use the previously computed base
value so it respects v7Features and configBasePath; update the conf.assetPrefix
assignment in the conf object to derive from base instead of using the hardcoded
`${templateLess ? pathPagePrefix : '/pt'}/${templateName}` expression (e.g.,
build assetPrefix by joining base and templateName while normalizing slashes) so
assets are emitted under the same base path the middleware expects (references:
conf, assetPrefix, base, templateLess, pathPagePrefix, templateName).
- Around line 757-761: Normalize opts.host once into a normalizedHost variable
(e.g., const normalizedHost = typeof opts.host === 'string' ? opts.host :
'localhost') and use that variable for nextOptions.hostname instead of casting
(opts.host as string) and also pass the same normalizedHost to the HTTP server
listen call; update references in the nextOptions construction
(nextOptions.hostname) and the httpServer.listen invocation to use
normalizedHost so the Next.js server and HTTP server bind to the same host.

In `@tests/test-nextjs-cjs/package.json`:
- Line 14: The package.json's "lint" npm script still calls "next lint" which
was removed in Next.js 16; update the "lint" script entry in package.json to use
ESLint directly by replacing the value of the "lint" script with "eslint ."
(since ESLint is already present in devDependencies) so the script runs
correctly with Next 16.2.2.

In `@tests/test-nextjs/package.json`:
- Line 29: The fixture's package.json still uses the removed "next lint" command
in the "lint" script after upgrading "next" to 16; update the "lint" script in
package.json (the "lint" script entry and the duplicate at lines referenced
51-52) to invoke ESLint directly (e.g., run eslint over the project with the
appropriate extensions and options) and ensure ESLint is added to
devDependencies so the script works independently of Next.js.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5b379f2e-4d00-4841-971f-55a2add79f24

📥 Commits

Reviewing files that changed from the base of the PR and between 57edeff and 97f0178.

⛔ Files ignored due to path filters (4)
  • package-lock.json is excluded by !**/package-lock.json
  • tests/test-commonjs/package-lock.json is excluded by !**/package-lock.json
  • tests/test-nextjs-cjs/package-lock.json is excluded by !**/package-lock.json
  • tests/test-nextjs/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • CHANGELOG.md
  • package.json
  • scripts/patch-npm-bundled-vulnerabilities.mjs
  • src/cli.ts
  • tests/test-commonjs/package.json
  • tests/test-nextjs-cjs/package.json
  • tests/test-nextjs-cjs/tsconfig.json
  • tests/test-nextjs/package.json

Comment thread CHANGELOG.md
Comment on lines +1 to +11
# [0.17.0-beta.1](https://github.com/mi-examples/pp-dev/compare/v0.16.1...v0.17.0-beta.1) (2026-04-06)


### Bug Fixes

* **tests:** align sandbox overrides with audited dependency policy ([5841aa8](https://github.com/mi-examples/pp-dev/commit/5841aa831833d74342e9bc134141f9913c1c0bab))


### Features

* **cli:** Webpack fallback for Next dev when Turbopack native SWC fails ([5940f31](https://github.com/mi-examples/pp-dev/commit/5940f316cf86056196ad3f69a8b3667460866aeb))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix the heading jump and expand the release notes.

The new entry goes from # to ###, which is why markdownlint reports MD001 here. I'd also call out the dependency/toolchain compatibility changes and the packaged security patch in this release so the changelog matches what 0.17.0-beta.1 actually ships.

As per coding guidelines, "Use proper markdown headers (##, ###) for GitHub compatibility in PR messages", "List specific technical improvements in PR messages", and "Specify breaking changes or compatibility in PR messages".

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 4-4: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CHANGELOG.md` around lines 1 - 11, The release header uses a single '#' which
triggers MD001 and skips a proper top-level release grouping; change the header
for the release "[0.17.0-beta.1]" from '#' to '##' and add or expand a short
"Highlights" or "Compatibility" subsection (under that release) calling out the
dependency/toolchain compatibility changes (e.g., Turbopack/SWC fallback
behavior) and the packaged security patch, and include a brief "Breaking Changes
/ Compatibility" note if any; update the existing "Bug Fixes" and "Features"
entries (5841aa8, 5940f31) to include one-line technical details so the
changelog matches the shipped contents and satisfies the markdownlint and PR
message guidelines.

Comment on lines +13 to +19
function replaceDir(src, dest) {
if (!existsSync(src) || !existsSync(dirname(dest))) {
return;
}
rmSync(dest, { recursive: true, force: true });
cpSync(src, dest, { recursive: true });
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don't let a best-effort postinstall patch fail the install.

This helper is called from the published postinstall hook, so any rmSync/cpSync exception here turns a security cleanup into a hard install failure for consumers. Wrap the filesystem mutation in try/catch and warn instead of throwing.

🔧 Safer postinstall patching
 function replaceDir(src, dest) {
   if (!existsSync(src) || !existsSync(dirname(dest))) {
     return;
   }
-  rmSync(dest, { recursive: true, force: true });
-  cpSync(src, dest, { recursive: true });
+  try {
+    rmSync(dest, { recursive: true, force: true });
+    cpSync(src, dest, { recursive: true });
+  } catch (error) {
+    console.warn(
+      `[pp-dev] Skipping bundled npm patch for ${dest}: ${
+        error instanceof Error ? error.message : String(error)
+      }`,
+    );
+  }
 }
📝 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.

Suggested change
function replaceDir(src, dest) {
if (!existsSync(src) || !existsSync(dirname(dest))) {
return;
}
rmSync(dest, { recursive: true, force: true });
cpSync(src, dest, { recursive: true });
}
function replaceDir(src, dest) {
if (!existsSync(src) || !existsSync(dirname(dest))) {
return;
}
try {
rmSync(dest, { recursive: true, force: true });
cpSync(src, dest, { recursive: true });
} catch (error) {
console.warn(
`[pp-dev] Skipping bundled npm patch for ${dest}: ${
error instanceof Error ? error.message : String(error)
}`,
);
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/patch-npm-bundled-vulnerabilities.mjs` around lines 13 - 19, The
replaceDir helper currently performs rmSync and cpSync which can throw and abort
consumers' installs; modify replaceDir (the function named replaceDir) to wrap
the filesystem mutation calls (rmSync and cpSync) in a try/catch block so any
exceptions are caught, and on error emit a non-fatal warning (e.g., console.warn
or the module's logger) with contextual info including src, dest and the caught
error; retain the existing existsSync checks (src and dirname(dest)) before
attempting mutations and return early as now, but ensure failures during
rmSync/cpSync do not rethrow.

Comment thread src/cli.ts
Comment on lines +757 to +761
const nextOptions: Parameters<typeof next>[0] = {
dev: true,
customServer: true,
hostname: (opts.host as string) || 'localhost',
port: opts.port,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's check the exact code at lines 757-761
sed -n '750,770p' src/cli.ts

Repository: mi-examples/pp-dev

Length of output: 661


🏁 Script executed:

# Now let's find all usages of opts.host in the file to understand the pattern
rg -n 'opts\.host' src/cli.ts -B 2 -A 2

Repository: mi-examples/pp-dev

Length of output: 500


🏁 Script executed:

# Let's also check the type of opts to understand opts.host
rg -n 'typeof opts\.host' src/cli.ts -B 3 -A 3

Repository: mi-examples/pp-dev

Length of output: 383


🏁 Script executed:

# Find the httpServer.listen call to see how host is used there
rg -n 'httpServer\.listen' src/cli.ts -B 5 -A 5

Repository: mi-examples/pp-dev

Length of output: 484


🏁 Script executed:

# Let's get a broader view of the function containing lines 757-761
sed -n '720,820p' src/cli.ts

Repository: mi-examples/pp-dev

Length of output: 3229


🏁 Script executed:

# Find the type definition or interface for opts
rg -n 'opts.*:' src/cli.ts -B 5 -A 5 | head -100

Repository: mi-examples/pp-dev

Length of output: 977


🏁 Script executed:

# Search for options or interface definitions near the function
rg -n 'interface.*Options|type.*Options' src/cli.ts

Repository: mi-examples/pp-dev

Length of output: 342


🏁 Script executed:

# Look for where opts is defined/destructured in the command definition
rg -n '\(options\)|\(opts\)' src/cli.ts -B 3 -A 3 | head -50

Repository: mi-examples/pp-dev

Length of output: 1836


🏁 Script executed:

# Check yargs/commander configuration for --host flag to understand its type
rg -n '\-\-host|host.*boolean|host.*string' src/cli.ts -B 2 -A 2

Repository: mi-examples/pp-dev

Length of output: 1478


Normalize opts.host once before building the Next server options.

The CLI option accepts string | boolean (bare --host flag sets it to true). Line 760 unsafely casts to string without a type check, so opts.host === true becomes the string "true" and passes through to next(). Meanwhile, lines 845–846 correctly handle the boolean case by checking type first and defaulting to 'localhost'. This causes the Next.js and HTTP servers to bind to different hosts when using the bare --host flag.

🔧 Suggested normalization
+          const normalizedHost =
+            opts.host === true
+              ? '0.0.0.0'
+              : typeof opts.host === 'string' && opts.host
+                ? opts.host
+                : 'localhost';
+
           const nextOptions: Parameters<typeof next>[0] = {
             dev: true,
             customServer: true,
-            hostname: (opts.host as string) || 'localhost',
+            hostname: normalizedHost,
             port: opts.port,
             dir: projectRoot,

Mirror the same normalizedHost in the later httpServer.listen() call at line 1152.

📝 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.

Suggested change
const nextOptions: Parameters<typeof next>[0] = {
dev: true,
customServer: true,
hostname: (opts.host as string) || 'localhost',
port: opts.port,
const normalizedHost =
opts.host === true
? '0.0.0.0'
: typeof opts.host === 'string' && opts.host
? opts.host
: 'localhost';
const nextOptions: Parameters<typeof next>[0] = {
dev: true,
customServer: true,
hostname: normalizedHost,
port: opts.port,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli.ts` around lines 757 - 761, Normalize opts.host once into a
normalizedHost variable (e.g., const normalizedHost = typeof opts.host ===
'string' ? opts.host : 'localhost') and use that variable for
nextOptions.hostname instead of casting (opts.host as string) and also pass the
same normalizedHost to the HTTP server listen call; update references in the
nextOptions construction (nextOptions.hostname) and the httpServer.listen
invocation to use normalizedHost so the Next.js server and HTTP server bind to
the same host.

Comment thread src/cli.ts
Comment on lines +763 to +767
conf: {
...config,
basePath: base,
assetPrefix: `${templateLess ? pathPagePrefix : '/pt'}/${templateName}`,
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use the computed base path for assetPrefix too.

base already handles /p, /pl, /pt, and custom basePath, but assetPrefix ignores v7Features and configBasePath. In the /pl/... path, Next will emit asset URLs under /pt/... while the middleware only exempts base and bare /_next paths, so static assets get pushed through proxy/cache instead of being served by Next.

🔧 Proposed fix
           conf: {
             ...config,
             basePath: base,
-            assetPrefix: `${templateLess ? pathPagePrefix : '/pt'}/${templateName}`,
+            assetPrefix: base,
           },
📝 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.

Suggested change
conf: {
...config,
basePath: base,
assetPrefix: `${templateLess ? pathPagePrefix : '/pt'}/${templateName}`,
},
conf: {
...config,
basePath: base,
assetPrefix: base,
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli.ts` around lines 763 - 767, The assetPrefix should use the previously
computed base value so it respects v7Features and configBasePath; update the
conf.assetPrefix assignment in the conf object to derive from base instead of
using the hardcoded `${templateLess ? pathPagePrefix : '/pt'}/${templateName}`
expression (e.g., build assetPrefix by joining base and templateName while
normalizing slashes) so assets are emitted under the same base path the
middleware expects (references: conf, assetPrefix, base, templateLess,
pathPagePrefix, templateName).

"dependencies": {
"@metricinsights/pp-dev": "file:../../metricinsights-pp-dev-latest.tgz",
"next": "^16.2.0",
"next": "^16.2.2",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the package.json file to see the current state
cat -n tests/test-nextjs-cjs/package.json

Repository: mi-examples/pp-dev

Length of output: 1578


🌐 Web query:

Next.js 16 next lint command removed upgrade guide

💡 Result:

In Next.js 16, the next lint command is removed, and next build no longer runs linting. You now need to run a linter directly (e.g., ESLint CLI or Biome). [1]

Recommended upgrade path (official)

Run the codemod that migrates next linteslint:

npx `@next/codemod`@canary next-lint-to-eslint-cli .

It will (among other things) update package.json scripts to use eslint ., create an eslint.config.mjs (flat config) with Next.js recommended rules, and add needed ESLint deps. [2]

Manual checklist (if you don’t use the codemod)

  • Replace your script:
    • lint: "next lint"lint: "eslint ." [2]
  • Remove the eslint option in next.config.* (it’s no longer supported in v16). [1]
  • If your CI relied on next build to lint, add an explicit lint step (e.g., run npm run lint) since builds won’t lint anymore. [1]

Timeline note

next lint was deprecated in Next.js 15.5 and removed in Next.js 16. [3]

Sources: Next.js v16 upgrade guide [1], Next.js codemods docs (next-lint-to-eslint-cli) [2], Next.js discussion noting deprecation/removal timeline [3].


Update the lint script to use ESLint directly; next lint was removed in Next.js 16.

The fixture is bumped to Next 16.2.2, but the lint script still references next lint, which no longer exists. This will cause the lint task to fail immediately. ESLint is already available as a dependency (lines 25–26), so update the script to "lint": "eslint .".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test-nextjs-cjs/package.json` at line 14, The package.json's "lint" npm
script still calls "next lint" which was removed in Next.js 16; update the
"lint" script entry in package.json to use ESLint directly by replacing the
value of the "lint" script with "eslint ." (since ESLint is already present in
devDependencies) so the script runs correctly with Next 16.2.2.

"jsdom": "28.0.0",
"memory-cache": "^0.2.0",
"next": "^16.2.0",
"next": "^16.2.2",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the actual package.json file to see the lint script
cat -n tests/test-nextjs/package.json | head -40

Repository: mi-examples/pp-dev

Length of output: 1400


🏁 Script executed:

# Let's check what Next.js version was used before (if there's git history available)
git log --oneline -n 20 -- tests/test-nextjs/package.json 2>/dev/null || echo "No git history available"

Repository: mi-examples/pp-dev

Length of output: 109


🏁 Script executed:

# Search for any lint-related scripts or references in the entire fixture
rg "next lint|\"lint\"" tests/test-nextjs/

Repository: mi-examples/pp-dev

Length of output: 116


🌐 Web query:

Next.js 16 next lint command removed upgrade guide

💡 Result:

In Next.js 16, the next lint command is removed, and next build no longer runs linting automatically. You must run your linter directly (e.g., ESLint CLI or Biome). Also, the eslint option in next.config.* is removed. [1]

Recommended upgrade path (official)

1) Run the codemod (migrates next linteslint .)

pnpm dlx `@next/codemod`@canary next-lint-to-eslint-cli .
# or: npx `@next/codemod`@canary next-lint-to-eslint-cli .

This codemod updates your package.json scripts (e.g. "lint": "eslint ."), adds needed ESLint deps, and can generate an eslint.config.mjs using Next’s recommended configs (while preserving existing config when found). [2]

2) Remove eslint from next.config.*

// next.config.mjs / next.config.js
export default {
  // eslint: {}, // remove (no longer supported)
}

[1]

3) Update CI/build pipelines

If you previously relied on next build to lint, add an explicit lint step (e.g. pnpm lint / npm run lint) since builds won’t lint anymore. [1]

Why this changed (context)

next lint was deprecated in Next.js 15.5 and then removed in Next.js 16 to decouple linting from the Next CLI and better support alternative linters (like Biome). [3]

Sources: [1] Next.js “Upgrading: Version 16” guide, [2] Next.js codemod docs (next-lint-to-eslint-cli), [3] Next.js repo discussion noting deprecation/removal.


🏁 Script executed:

# Check lines 51-52 to see what else needs updating
sed -n '48,55p' tests/test-nextjs/package.json

Repository: mi-examples/pp-dev

Length of output: 279


🏁 Script executed:

# Let's also check if there's an eslintrc or eslint config in the fixture
find tests/test-nextjs -name "*eslint*" -o -name ".eslintrc*"

Repository: mi-examples/pp-dev

Length of output: 94


🏁 Script executed:

# Get better context around lines 48-54
sed -n '46,54p' tests/test-nextjs/package.json | cat -n

Repository: mi-examples/pp-dev

Length of output: 381


🏁 Script executed:

# Let's see the full devDependencies section
sed -n '41,60p' tests/test-nextjs/package.json | cat -n

Repository: mi-examples/pp-dev

Length of output: 776


🏁 Script executed:

# Let's check the ESLint config to understand the linting setup
cat -n tests/test-nextjs/.eslintrc.json

Repository: mi-examples/pp-dev

Length of output: 122


Migrate the fixture's lint command as part of the Next 16 upgrade.

This change bumps the fixture to Next 16, but its existing lint script still shells out to next lint. Next.js 16 removed that command and no longer runs linting during next build, so this fixture will regress as soon as anyone runs lint. Switch the script to ESLint directly in the same upgrade. (nextjs.org)

Also applies to: 51-52

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test-nextjs/package.json` at line 29, The fixture's package.json still
uses the removed "next lint" command in the "lint" script after upgrading "next"
to 16; update the "lint" script in package.json (the "lint" script entry and the
duplicate at lines referenced 51-52) to invoke ESLint directly (e.g., run eslint
over the project with the appropriate extensions and options) and ensure ESLint
is added to devDependencies so the script works independently of Next.js.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants