Skip to content

chore(deps): update dependencies, including majors - #5743

Merged
alexander-akait merged 6 commits into
mainfrom
claude/webpack-dev-server-pr-consolidation-t0k72z
Sep 18, 2026
Merged

alexander-akait merged 6 commits into
mainfrom
claude/webpack-dev-server-pr-consolidation-t0k72z

Conversation

@alexander-akait

@alexander-akait alexander-akait commented Sep 18, 2026

Copy link
Copy Markdown
Member

Summary

Takes the in-range bumps from #5738 (41 packages, lockfile only) and, on top of them, 17 of the 23 available majors. Closes #5738.

Held back deliberately:

Package Why
eslint 10, typescript 7 As requested, not now.
@babel/core, @babel/cli, @babel/preset-env 8, babel-plugin-transform-import-meta 3 Babel 8 has no stable @babel/plugin-transform-object-assign — only 8.0.0-beta.*. That plugin is what babel.config.js and client-src/webpack.config.js use to keep Object.assign working on old browsers, so Babel 8 means shipping a beta or dropping that support. It deserves its own decision rather than riding along here.

Taken: @changesets/cli 3, @changesets/get-github-info 1, @commitlint/cli + config-conventional 21, @eslint/markdown 8, @hono/node-server 2, @types/node 26, cspell 10, eslint-plugin-jsdoc 64, eslint-plugin-n 18, execa 10, jsdom 30, less-loader 13, lint-staged 17, marked 18, rimraf 6, wait-for-expect 4.

What the upgrades actually required:

  • execa 10 dropped its default export and its subprocess is no longer an event emitter — cp.on("exit") / cp.on("error") are gone. The CLI lifecycle tests now settle on the subprocess promise, with reject: false where a non-zero exit is the expected outcome.
  • @changesets/get-github-info 1 replaced getInfo/getInfoFromPullRequest with getCommitInfo/getPullRequestInfo, returning structured objects that may be undefined instead of a links map of markdown strings. The changelog generator is ported. The package is ESM-only behind an exports map that the import resolver cannot follow, so import/no-unresolved is disabled for that single file.
  • @types/node 26 types socket.server, so a @ts-expect-error in lib/Server.js became unused.
  • webpack 5.111 (in range) reworded its module-parse diagnostic to name the module type and add a code frame; the four overlay snapshots capturing that text are regenerated.
  • prettier 3.9 (in range) reformats lib/Server.js, test/e2e/client.test.js and migration-v4.md. Those hunks are prettier's own output, not hand edits — worth knowing that chore(deps): bump the dependencies group across 1 directory with 41 updates #5738 on its own would fail fmt:check for exactly this reason.

What kind of change does this PR introduce?

chore

Did you add tests for your changes?

No new tests — this is a dependency update. Existing tests were used to qualify it, and the execa migration was measured against a main baseline rather than assumed: test/cli/basic.test.js is 17/17 on main with execa 5 and 17/17 here with execa 10 (it was 5/17 mid-migration, which is how the missing event-emitter API was found). Also run: all test/cli 103/105, test/client + test/server 168/170, and ~20 e2e suites at 165/166 plus overlay 38/38 — every remaining failure is a sandbox limitation (no IPv6, and test.host resolving here) that reproduces identically on main. Full lint chain, build, build:types, changeset-validate, commitlint and changeset status all clean; all 50 examples/**/webpack.config.* still load and validate, and the hono example was smoke-tested end to end under @hono/node-server 2.

Does this PR introduce a breaking change?

No. The published dependencies ranges are unchanged — every major taken here is a devDependency. The only generated-type movement is cosmetic (import("http")import("node:http") and prettier reflowing unions).

If relevant, what needs to be documented once your changes are merged or what have you already documented?

n/a. Note for later: several devDependencies now want Node ≥ 22.18–22.22 while engines says >= 22.15.0. That only affects contributors installing on an old 22.x, not consumers, and CI uses 22.x (latest).

Use of AI

Claude Code applied the updates, checked each major's peer requirements and engine ranges before taking it, migrated the code the breaking ones required, and ran the verification above — including building a main worktree with execa 5 to get a true before/after for the CLI suite.


Generated by Claude Code

Summary by CodeRabbit

  • Documentation

    • Updated the v4 Node.js API example to use the current constructor argument order.
  • Compatibility

    • Improved TypeScript declarations for Node.js HTTP and WebSocket integrations.
    • Improved support for modern JavaScript module and object-assignment transformations.
  • Maintenance

    • Improved changelog links for commits, pull requests, and authors.
    • Updated development tooling and automated workflows.
    • Removed commit message linting.
  • Tests

    • Modernized command execution and file-watching tests.
    • Refreshed diagnostic and validation snapshots.
    • Improved test-server cleanup to prevent lingering ports and listeners.

@changeset-bot

changeset-bot Bot commented Sep 18, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 08dceaf

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@socket-security

socket-security Bot commented Sep 18, 2026

Copy link
Copy Markdown

@coderabbitai

coderabbitai Bot commented Sep 18, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: f62648a5-29c4-4bf5-bca2-683e3d29c169

📥 Commits

Reviewing files that changed from the base of the PR and between 00c24df and 08dceaf.

📒 Files selected for processing (1)
  • test/e2e/watch-files.test.js

Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.


Walkthrough

The pull request updates development dependencies and adapts integrations to newer APIs. Changelog generation now uses structured GitHub information responses. Execa-based tests use named imports and promise handling. Public Node.js type references use node:http. The migration guide documents the v4 constructor order. Webpack overlay snapshots include expanded diagnostics. Server cleanup now tracks pending shutdowns and closes rejected servers. Several server changes only reformat existing code.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 08dce

The dependency compatibility and watch-test synchronization updates have no identified merge-blocking risk.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 17 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: dependency updates that include major-version upgrades. It is concise and consistent with the pull request objectives.
Linked Issues check ✅ Passed The pull request meets the coding requirements in #5738. The summary reports 41 root dependency updates, consistent lockfile and dependency metadata refreshes, and migrations for execa and `@changes…
Out of Scope Changes check ✅ Passed The changes remain within the scope of #5738. Source migrations, Babel compatibility plugins, type updates, snapshot updates, test-harness cleanup, workflow action updates, and removal of obsolete Com…
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

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

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

🟡 Minor · Reject failed subprocess results in the stdin test. · basic.test.js:180-210

test/cli/basic.test.js:180-210
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject failed subprocess results in the stdin test. With execa@10.0.1 and reject: false, a spawn failure or nonzero exit resolves cp with result.failed === true. The current cp.then(() => resolve()) ignores that result. The cp.stdin error listener only handles stdin-stream errors, and expect(cp.pid) runs only after stdout data. Therefore, a failure before stdout can resolve the outer test without exercising the assertion. This test calls execa directly, so testBin does not detect the failure.

Suggested fix
-        cp.then(() => {
+        cp.then((result) => {
+          if (result.failed) {
+            reject(result);
+            return;
+          }
+
           resolve();
         });

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: e45da9b8-aa25-4f0d-8f4d-775286d8fe96

📥 Commits

Reviewing files that changed from the base of the PR and between d09c426 and 38fd037.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (11)
  • .changeset/changelog-generator.mjs
  • eslint.config.mjs
  • lib/Server.js
  • migration-v4.md
  • package.json
  • test/cli/basic.test.js
  • test/e2e/__snapshots__/overlay.test.js.snap.webpack5
  • test/e2e/client.test.js
  • test/helpers/test-bin.js
  • types/lib/Server.d.ts
  • types/lib/servers/WebsocketServer.d.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 4 remain after this review.

alexander-akait and others added 2 commits September 18, 2026 16:35
Applies the in-range bumps from #5738 (41 packages, lockfile only) and
takes 17 of the 23 available majors. `eslint` and `typescript` are held
back as asked.

`@babel/core`, `@babel/cli`, `@babel/preset-env` and
`babel-plugin-transform-import-meta` are also held back: Babel 8 has no
stable `@babel/plugin-transform-object-assign`, only `8.0.0-beta.*`, and
that plugin is what the client build uses to keep `Object.assign` working
on old browsers. Taking Babel 8 would mean shipping a beta or dropping
that support, so it needs its own decision.

What the upgrades required:

- `execa` 10 no longer returns an event emitter, so `cp.on("exit")` and
  `cp.on("error")` are gone. The CLI lifecycle tests now settle on the
  subprocess promise, with `reject: false` where a non-zero exit is the
  expected outcome. It also dropped its default export.
- `@changesets/get-github-info` 1 replaced `getInfo`/`getInfoFromPullRequest`
  with `getCommitInfo`/`getPullRequestInfo`, which return structured objects
  that may be `undefined` rather than a `links` map of markdown strings.
  The changelog generator is ported to that shape. The package is ESM-only
  behind an `exports` map the import resolver cannot follow, so
  `import/no-unresolved` is disabled for that one file.
- `@types/node` 26 types `socket.server`, so a `@ts-expect-error` in
  `lib/Server.js` became unused and had to go.
- webpack 5.111 (in range) reworded its module-parse diagnostic to name the
  module type and include a code frame; the four overlay snapshots that
  capture that text are regenerated.
- prettier 3.9 (in range) reformats `lib/Server.js`, `test/e2e/client.test.js`
  and `migration-v4.md`. These are its output, not hand edits — #5738 on its
  own would fail `fmt:check` without them.

No changeset: the published `dependencies` ranges are unchanged, so nothing
here reaches consumers.
Four cleanups that all reduce what the repository has to install or pin.

Remove commitlint. It is no longer used, so the two `@commitlint/*` packages,
`commitlint.config.js`, the `.husky/commit-msg` hook, the npm script and the
pull request step in CI all go. `fetch-depth: 0` stays on the lint job's
checkout: `validate:changeset` still diffs against `origin/$GITHUB_BASE_REF`.

Stop declaring the eslint plugins. `eslint-config-webpack` depends on
`@eslint/markdown`, `eslint-config-prettier`, `eslint-plugin-import`,
`eslint-plugin-jsdoc`, `eslint-plugin-n` and `typescript-eslint` itself, and
flat config resolves a plugin from the config that names it rather than from
the project root, so declaring them here only pins a second, drifting copy —
ours held `eslint-plugin-jsdoc` a major ahead of the config's own range.
`eslint` and `typescript` stay, as the config's two peers.
`@babel/eslint-parser` goes too: nothing references it.

Update babel to 8. The blocker was `@babel/plugin-transform-object-assign`,
which babel never released for 8 — it is pinned to `@babel/core@^7` even on
its `8.0.0-beta.4` tag. The plugin is twelve lines and the client build does
need it, because the bundled `webpack/lib/logging/runtime.js` calls
`Object.assign`, so it is now a local plugin next to the one this repo already
had. Babel 8 also parses `import()` as `ImportExpression` rather than a
`CallExpression` with an `Import` callee, which silently stopped
`rewrite-relative-dynamic-import` from rewriting anything; it now visits the
new node and declines an `import()` carrying attributes, which has no
`require()` equivalent. `babel-plugin-transform-import-meta` 3 moves with it —
it requires `@babel/core@^8.0.1`.

`dist/` is byte-identical to the babel 7 output, both with the local plugin on
babel 7 and after the upgrade. `client/` differs only in where babel emits its
`_inherits` helper.

Update the github actions: checkout 6 to 7, setup-node 6 to 7,
upload-artifact 4 to 7, download-artifact 4 to 8, codecov-action 6 to 7 and
changesets/action 1 to 2, each pinned to the release tag's commit.
`changesets/action` 2 is the one with a migration: it is the version built for
changesets 3, which this repository now installs, and it renamed the three
inputs used here. It also no longer touches `.npmrc`, so the `NPM_TOKEN: ""`
workaround is gone; `GITHUB_TOKEN` stays because `changeset version` runs the
changelog generator, which queries the GitHub API.

`schema-utils` 4.5.0 prints the type of a simple optional property, so the
`validate-options` snapshots that quote it are regenerated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
@alexander-akait
alexander-akait force-pushed the claude/webpack-dev-server-pr-consolidation-t0k72z branch from 38fd037 to b39ecaa Compare September 18, 2026 17:27
alexander-akait and others added 2 commits September 18, 2026 17:43
`validate-options` snapshotted `thrownError.toString()`, which is
`schema-utils` rendering the whole of `lib/options.json` into prose: every
sibling property's type, the `description` and `link` text, the entire `anyOf`
tree. None of that is this project's behaviour, so the snapshots moved whenever
schema-utils or ajv did — 4.5.0 rewrote ten of them, and CI went red, by
spelling out the type of simple optional properties (`directory?` became
`directory?: non-empty string`) in options the release never touched.

What is ours is which option path the error blames, so that is what it
snapshots now, alongside an assertion that a `ValidationError` was thrown and
named at least one path. `allowedHosts: [""]` still reads as
`options.allowedHosts[0]` rather than `options.allowedHosts`, so a schema
mis-nesting still fails, and the file is 355 lines shorter and reviewable.

The second one only shows up as a difference between runs. A test that throws
between `server.start()` and `server.stop()` never reaches its own cleanup, so
the server keeps the port and every later test in the file fails with
`EADDRINUSE`. One genuine failure is then reported as dozens, and which ones
depends on timing — `host.test.js` gave 25, 27 and 33 failures on three runs of
identical code. The harness now tracks listening servers and stops whatever a
test leaves behind, exempting the ones a `before` hook started for a whole
suite, which are already listening when the first test begins.

Nothing in the suite stops relying on its own cleanup; this only bounds the
damage when that cleanup is skipped. On this machine, whose sandbox has no
IPv6 and no routable address, `host.test.js` goes from 5 passing to 15, with no
`EADDRINUSE` left and the same 15/15 split on three consecutive runs, and the
e2e suite as a whole from 453 passing to 463.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
`CodeRabbit` pointed out that with `reject: false` a subprocess which never
started settles like a healthy one, so `cp.then(() => resolve())` resolves the
test without reaching any assertion. That is right, and it turned out not to be
hypothetical: the two SIGINT tests passed `["--port", port, cliPath]` to node,
which takes `--port` as one of its own options and exits 9 with
`node: bad option: --port` before the CLI is ever loaded. No output, no signal
sent, and both tests green. They have been vacuous since long before this
branch; the execa migration carried the shape over, and only asserting on the
result exposes it.

So the CLI path now goes first, and all four record whether their trigger fired
and assert on how the subprocess ended: a clean exit for the SIGINT pair, which
is the evidence the CLI's trap ran rather than that something killed it, and
for the stdin pair too. Windows has no POSIX signals — `kill("SIGINT")`
terminates outright, so the trap cannot run — and only that assertion is
skipped there.

Put back the old argument order and all four now fail, where before they
passed.

The stdin writes can land after the subprocess is gone; an unhandled `error` on
that stream would take the test process down, so it is swallowed and the
subprocess result is the verdict.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA

@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: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: f53c7ae8-0d82-436f-adf6-0a4ecfa04278

📥 Commits

Reviewing files that changed from the base of the PR and between 38fd037 and 8616e89.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (15)
  • .cspell.json
  • .github/workflows/dependency-review.yml
  • .github/workflows/nodejs.yml
  • .github/workflows/release.yml
  • .husky/commit-msg
  • babel.config.js
  • client-src/webpack.config.js
  • commitlint.config.js
  • package.json
  • scripts/babel-plugin-rewrite-relative-dynamic-import.mjs
  • scripts/babel-plugin-transform-object-assign.mjs
  • scripts/node-test-setup.mjs
  • test/__snapshots__/validate-options.test.js.snap.webpack5
  • test/cli/basic.test.js
  • test/validate-options.test.js
💤 Files with no reviewable changes (3)
  • .cspell.json
  • .husky/commit-msg
  • commitlint.config.js

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Comment thread scripts/node-test-setup.mjs Outdated
alexander-akait and others added 2 commits September 18, 2026 18:27
`CodeRabbit` is right that the sweep dropped a server from the tracked set the
moment `stop()` was called rather than when it finished. A shutdown that
rejects leaves the port held and the server untracked, so `afterEach` saw
nothing to clean up and the next test got the `EADDRINUSE` the sweep exists to
prevent; a `stop()` a test never awaits has the same shape. No test does the
latter today, but the sweep is there for when things go wrong, so both count.

A server now leaves the set only once its shutdown has actually resolved, and
`afterEach` settles any shutdown still in flight before deciding what leaked.
When the retry rejects too, the listener is closed directly: `stop()` can
reject before it ever reaches `this.server.close()`, and that port is exactly
what the next test pays for.

`test/harness-server-cleanup.test.js` covers the three ways a server survives
its test — left running, stopped without awaiting, and a shutdown that rejects
— each followed by a test that has to bind the same port again. All six pass
with the sweep; five fail without it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
`watch-files.test.js` hung for its full 400s timeout on CI. The cause is
structural rather than environmental: the two multi-path tests write two files
and then wait for `changed === 2`, where each `change` handler awaits its own
`page.waitForNavigation()`. The server sends one reload for both writes —
measured, two change events at +0ms and exactly one main-frame navigation — so
the two handlers are both relying on latching onto that single navigation.

They only do when both change events land in the same tick. In different poll
cycles the first handler consumes the navigation and the second registers after
it has already finished, waits out the 120s navigation timeout, and has its
rejection swallowed because the handler is an uncaught `async` function. The
outer promise then never settles and the test burns the whole timeout with a
message that names nothing.

So those two now wait for one navigation and assert what is actually under
test: that the watcher reports both paths.

The single-file tests are rewritten the same way, arming both waits before the
write and joining them with `Promise.all`. The race does not arise there — the
write is synchronous and the handler runs in the same tick — but the swallowed
rejection does: any navigation failure became a 400s hang rather than a
`TimeoutError` naming the page. `multi-compiler.test.js` and `logging.test.js`
look similar and are deliberately untouched: their `waitForNavigation()` is
already called in the same synchronous block as the write, so there is nothing
to fix and the churn would only hide this change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
@alexander-akait
alexander-akait merged commit 9b4dd8c into main Sep 18, 2026
12 of 14 checks passed
@alexander-akait
alexander-akait deleted the claude/webpack-dev-server-pr-consolidation-t0k72z branch September 18, 2026 20:22
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.

1 participant