From 8ec9e7ffca64b12ffa870a8f99d6cd502a83ee1f Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Fri, 11 Jul 2025 23:37:52 +0530 Subject: [PATCH 1/8] chore: upgrade eslint to v6 --- CHANGELOG.md | 24 +- DOCUMENTATION-v4.md | 196 +- README.md | 6 +- bin/webpack-dev-server.js | 29 +- client-src/webpack.config.js | 2 +- eslint.config.js | 22 + examples/api/simple/app.js | 2 +- examples/app/hono/webpack.config.js | 6 +- examples/client/overlay/app.js | 1 - examples/client/overlay/create-button.js | 1 - .../trusted-types-overlay/webpack.config.js | 2 +- .../general/proxy-hot-reload/proxy-config.js | 12 +- .../proxy-hot-reload/webpack.config.js | 5 +- examples/general/universal-config/client.js | 6 +- examples/general/webworker/worker.js | 2 +- examples/headers/function/README.md | 4 +- examples/headers/function/webpack.config.js | 4 +- examples/history-api-fallback/app.js | 9 +- examples/ipc/README.md | 2 +- examples/ipc/webpack.config.js | 2 +- examples/on-listening/README.md | 2 +- examples/on-listening/webpack.config.js | 2 +- examples/open-target-multiple/app1.js | 2 +- examples/open-target-multiple/app2.js | 2 +- examples/open-target/app.js | 2 +- examples/proxy/webpack.config.js | 3 + examples/server/https/README.md | 4 +- examples/util.js | 18 +- lib/Server.js | 176 +- lib/getPort.js | 18 +- lib/servers/SockJSServer.js | 5 +- lib/servers/WebsocketServer.js | 25 +- migration-v4.md | 20 +- migration-v5.md | 24 +- package-lock.json | 3272 +++++++++++++++-- package.json | 31 +- scripts/extend-webpack-types.js | 7 +- scripts/globalSetupTest.js | 16 +- scripts/prepare-test-for-old-node.js | 11 +- test/cli/allowedHosts-option.test.js | 8 +- test/cli/basic.test.js | 30 +- test/cli/bonjour-option.test.js | 10 +- test/cli/client-option.test.js | 38 +- test/cli/colors.test.js | 22 +- test/cli/compress-option.test.js | 4 +- test/cli/historyApiFallback-option.test.js | 6 +- test/cli/host-option.test.js | 248 +- test/cli/hot-option.test.js | 6 +- test/cli/ipc-option.test.js | 12 +- test/cli/liveReload-option.test.js | 4 +- test/cli/open-option.test.js | 26 +- test/cli/port-option.test.js | 8 +- test/cli/server-option.test.js | 22 +- test/cli/static-option.test.js | 26 +- test/cli/watchFiles-option.test.js | 10 +- test/cli/webSocketServer-option.test.js | 6 +- test/client/ReactErrorBoundary.test.js | 50 +- test/client/bundle.test.js | 2 +- test/client/clients/SockJSClient.test.js | 5 +- test/client/clients/WebsocketClient.test.js | 4 +- test/client/index.test.js | 88 +- test/client/socket-helper.test.js | 12 +- test/client/utils/createSocketURL.test.js | 21 +- .../utils/getCurrentScriptSource.test.js | 20 +- test/client/utils/log.test.js | 18 +- test/client/utils/sendMessage.test.js | 6 +- test/e2e/allowed-hosts.test.js | 10 +- test/e2e/api.test.js | 44 +- test/e2e/app.test.js | 19 +- test/e2e/bonjour.test.js | 74 +- test/e2e/built-in-routes.test.js | 2 +- test/e2e/client-reconnect.test.js | 8 +- test/e2e/client.test.js | 7 +- test/e2e/cross-origin-request.test.js | 12 +- test/e2e/entry.test.js | 2 +- test/e2e/headers.test.js | 8 +- test/e2e/history-api-fallback.test.js | 8 +- test/e2e/host.test.js | 4 +- test/e2e/hot-and-live-reload.test.js | 57 +- test/e2e/ipc.test.js | 18 +- test/e2e/lazy-compilation.test.js | 11 +- test/e2e/logging.test.js | 20 +- test/e2e/module-federation.test.js | 12 +- test/e2e/multi-compiler.test.js | 44 +- test/e2e/options-middleware.test.js | 4 +- test/e2e/overlay.test.js | 106 +- test/e2e/port.test.js | 12 +- test/e2e/progress.test.js | 8 +- test/e2e/range-header.test.js | 4 +- test/e2e/server-and-client-transport.test.js | 58 +- test/e2e/server.test.js | 20 +- test/e2e/setup-exit-signals.test.js | 8 +- test/e2e/static-directory.test.js | 23 +- test/e2e/static-public-path.test.js | 4 +- test/e2e/stats.test.js | 11 +- test/e2e/target.test.js | 8 +- test/e2e/watch-files.test.js | 8 +- test/e2e/web-socket-communication.test.js | 14 +- test/e2e/web-socket-server-url.test.js | 140 +- test/e2e/web-socket-server.test.js | 2 - test/helpers/ExitOnDonePlugin.js | 2 +- test/helpers/custom-http.js | 2 +- test/helpers/html-generator-plugin.js | 2 +- test/helpers/normalize-options.js | 4 +- test/helpers/run-browser.js | 74 +- test/helpers/session-subscribe.js | 4 +- test/helpers/snapshotResolver.js | 2 +- test/helpers/test-bin.js | 28 +- test/helpers/test-server.js | 21 +- .../trusted-types-html-generator-plugin.js | 1 - test/normalize-options.test.js | 25 +- test/ports-map.js | 7 +- test/server/open-option.test.js | 86 +- test/server/proxy-option.test.js | 106 +- test/validate-options.test.js | 18 +- types/lib/Server.d.ts | 9 +- types/lib/getPort.d.ts | 2 +- 117 files changed, 4066 insertions(+), 1806 deletions(-) create mode 100644 eslint.config.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 066cd4a0ce..3d99dd4206 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -575,9 +575,9 @@ module.exports = { module.exports = { entry: { entry: [ - 'whatwg-fetch', - 'core-js/features/promise', - './entry.js' + "whatwg-fetch", + "core-js/features/promise", + "./entry.js" ], }, }; @@ -589,13 +589,13 @@ module.exports = { module.exports = { entry: { entry: [ - 'whatwg-fetch', - 'core-js/features/promise', - './entry.js' + "whatwg-fetch", + "core-js/features/promise", + "./entry.js" ], }, devServer: { - transportMode: 'sockjs', + transportMode: "sockjs", }, }; ``` @@ -693,15 +693,15 @@ module.exports = { // static: false static: [ // Simple example - path.resolve(__dirname, 'static'), + path.resolve(__dirname, "static"), // Complex example { - directory: path.resolve(__dirname, 'static'), + directory: path.resolve(__dirname, "static"), staticOptions: {}, // Don't be confused with `dev.publicPath`, it is `publicPath` for static directory // Can be: // publicPath: ['/static-public-path-one/', '/static-public-path-two/'], - publicPath: '/static-public-path/', + publicPath: "/static-public-path/", // Can be: // serveIndex: {} (options for the `serveIndex` option you can find https://github.com/expressjs/serve-index) serveIndex: true, @@ -721,7 +721,7 @@ module.exports = { // ... devServer: { dev: { - publicPath: '/publicPathForDevServe', + publicPath: "/publicPathForDevServe", }, }, }; @@ -751,7 +751,7 @@ module.exports = { // Only warnings and errors // level: 'none' disable logging // Please read https://webpack.js.org/configuration/other-options/#infrastructurelogginglevel - level: 'warn', + level: "warn", }, }; ``` diff --git a/DOCUMENTATION-v4.md b/DOCUMENTATION-v4.md index 183ca01824..3e34dba4f9 100644 --- a/DOCUMENTATION-v4.md +++ b/DOCUMENTATION-v4.md @@ -15,10 +15,10 @@ This set of options is picked up by [webpack-dev-server](https://github.com/webp **webpack.config.js** ```javascript -const path = require("path"); +const path = require("node:path"); module.exports = { - //... + // ... devServer: { static: { directory: path.join(__dirname, "public"), @@ -89,7 +89,7 @@ This option allows you to allowlist services that are allowed to access the dev ```javascript module.exports = { - //... + // ... devServer: { allowedHosts: [ "host.com", @@ -107,7 +107,7 @@ Mimicking Django's `ALLOWED_HOSTS`, a value beginning with `.` can be used as a ```javascript module.exports = { - //... + // ... devServer: { // this achieves the same effect as the first example // with the bonus of not having to update your config @@ -129,7 +129,7 @@ When set to `'all'` this option bypasses host checking. **THIS IS NOT RECOMMENDE ```javascript module.exports = { - //... + // ... devServer: { allowedHosts: "all", }, @@ -148,7 +148,7 @@ When set to `'auto'` this option always allows `localhost`, [`host`](#devserverh ```javascript module.exports = { - //... + // ... devServer: { allowedHosts: "auto", }, @@ -171,7 +171,7 @@ This option broadcasts the server via [ZeroConf](http://www.zeroconf.org/) netwo ```javascript module.exports = { - //... + // ... devServer: { bonjour: true, }, @@ -196,7 +196,7 @@ You can also pass [custom options](https://github.com/watson/bonjour#initializin ```javascript module.exports = { - //... + // ... devServer: { bonjour: { type: "http", @@ -218,7 +218,7 @@ Allows to set log level in the browser, e.g. before reloading, before an error o ```javascript module.exports = { - //... + // ... devServer: { client: { logging: "info", @@ -243,7 +243,7 @@ Shows a full-screen overlay in the browser when there are compiler errors or war ```javascript module.exports = { - //... + // ... devServer: { client: { overlay: true, @@ -280,7 +280,7 @@ For example, to disable compilation warnings, you can provide the following conf ```javascript module.exports = { - //... + // ... devServer: { client: { overlay: { @@ -307,7 +307,7 @@ For example, to ignore errors thrown by [`AbortController.abort()`](https://deve ```javascript module.exports = { - //... + // ... devServer: { client: { overlay: { @@ -337,7 +337,7 @@ Prints compilation progress in percentage in the browser. ```javascript module.exports = { - //... + // ... devServer: { client: { progress: true, @@ -370,7 +370,7 @@ Tells dev-server the number of times it should try to reconnect the client. When ```javascript module.exports = { - //... + // ... devServer: { client: { reconnect: true, @@ -389,7 +389,7 @@ When set to `false` it will not try to reconnect. ```javascript module.exports = { - //... + // ... devServer: { client: { reconnect: false, @@ -408,7 +408,7 @@ You can also specify the exact number of times the client should try to reconnec ```javascript module.exports = { - //... + // ... devServer: { client: { reconnect: 5, @@ -437,7 +437,7 @@ This option allows us either to choose the current `devServer` transport mode fo ```javascript module.exports = { - //... + // ... devServer: { client: { webSocketTransport: "ws", @@ -465,7 +465,7 @@ Using path to `CustomClient.js`, a custom WebSocket client implementation, along ```javascript module.exports = { - //... + // ... devServer: { client: { webSocketTransport: require.resolve("./CustomClient"), @@ -481,7 +481,7 @@ Using custom, compatible WebSocket client and server implementations: ```javascript module.exports = { - //... + // ... devServer: { client: { webSocketTransport: require.resolve("./CustomClient"), @@ -501,7 +501,7 @@ This option allows specifying URL to web socket server (useful when you're proxy ```javascript module.exports = { - //... + // ... devServer: { client: { webSocketURL: "ws://0.0.0.0:8080/ws", @@ -529,7 +529,7 @@ You can also specify an object with the following properties: ```javascript module.exports = { - //... + // ... devServer: { client: { webSocketURL: { @@ -559,7 +559,7 @@ Enable [gzip compression](https://betterexplained.com/articles/how-to-optimize-y ```javascript module.exports = { - //... + // ... devServer: { compress: true, }, @@ -612,7 +612,7 @@ HTTP/2 with a self-signed certificate: ```javascript module.exports = { - //... + // ... devServer: { http2: true, }, @@ -636,10 +636,10 @@ Provide your own certificate using the [https](#devserverhttps) option: **webpack.config.js** ```javascript -const fs = require("fs"); +const fs = require("node:fs"); module.exports = { - //... + // ... devServer: { http2: true, https: { @@ -671,7 +671,7 @@ By default, dev-server will be served over `HTTP`. It can optionally be served o ```javascript module.exports = { - //... + // ... devServer: { https: true, }, @@ -722,8 +722,8 @@ npx webpack serve --https-request-cert --https-key ./path/to/server.key --https- **webpack.config.js** ```javascript -const fs = require("fs"); -const path = require("path"); +const fs = require("node:fs"); +const path = require("node:path"); module.exports = { devServer: { @@ -758,7 +758,7 @@ Adds headers to all responses: ```javascript module.exports = { - //... + // ... devServer: { headers: { "X-Custom-Foo": "bar", @@ -773,7 +773,7 @@ You can also pass an array: ```javascript module.exports = { - //... + // ... devServer: { headers: [ { @@ -793,11 +793,9 @@ You can also pass a function: ```javascript module.exports = { - //... + // ... devServer: { - headers: () => { - return { "X-Bar": ["key1=value1", "key2=value2"] }; - }, + headers: () => ({ "X-Bar": ["key1=value1", "key2=value2"] }), }, }; ``` @@ -812,7 +810,7 @@ When using the [HTML5 History API](https://developer.mozilla.org/en-US/docs/Web/ ```javascript module.exports = { - //... + // ... devServer: { historyApiFallback: true, }, @@ -837,7 +835,7 @@ By providing an object this behavior can be controlled further using options lik ```javascript module.exports = { - //... + // ... devServer: { historyApiFallback: { rewrites: [ @@ -856,7 +854,7 @@ When using dots in your path (common with Angular), you may need to use the `dis ```javascript module.exports = { - //... + // ... devServer: { historyApiFallback: { disableDotRule: true, @@ -877,7 +875,7 @@ Specify a host to use. If you want your server to be accessible externally, spec ```javascript module.exports = { - //... + // ... devServer: { host: "0.0.0.0", }, @@ -930,7 +928,7 @@ Enable webpack's [Hot Module Replacement](/concepts/hot-module-replacement/) fea ```javascript module.exports = { - //... + // ... devServer: { hot: true, }, @@ -955,7 +953,7 @@ To enable Hot Module Replacement without page refresh as a fallback in case of b ```javascript module.exports = { - //... + // ... devServer: { hot: "only", }, @@ -984,7 +982,7 @@ Setting it to `true` will listen to a socket at `/your-os-temp-dir/webpack-dev-s ```javascript module.exports = { - //... + // ... devServer: { ipc: true, }, @@ -1002,10 +1000,10 @@ You can also listen to a different socket with: **webpack.config.js** ```javascript -const path = require("path"); +const path = require("node:path"); module.exports = { - //... + // ... devServer: { ipc: path.join(__dirname, "my-socket.sock"), }, @@ -1022,7 +1020,7 @@ By default, the dev-server will reload/refresh the page when file changes are de ```javascript module.exports = { - //... + // ... devServer: { liveReload: false, }, @@ -1057,7 +1055,7 @@ Tell dev-server to enable/disable magic HTML routes (routes corresponding to you ```javascript module.exports = { - //... + // ... devServer: { magicHtml: true, }, @@ -1087,14 +1085,14 @@ internally within the server. ```javascript module.exports = { - //... + // ... devServer: { - onAfterSetupMiddleware: function (devServer) { + onAfterSetupMiddleware (devServer) { if (!devServer) { throw new Error("webpack-dev-server is not defined"); } - devServer.app.get("/some/path", function (req, res) { + devServer.app.get("/some/path", (req, res) => { res.json({ custom: "response" }); }); }, @@ -1118,14 +1116,14 @@ example: ```javascript module.exports = { - //... + // ... devServer: { - onBeforeSetupMiddleware: function (devServer) { + onBeforeSetupMiddleware (devServer) { if (!devServer) { throw new Error("webpack-dev-server is not defined"); } - devServer.app.get("/some/path", function (req, res) { + devServer.app.get("/some/path", (req, res) => { res.json({ custom: "response" }); }); }, @@ -1147,14 +1145,14 @@ Provides the ability to execute a custom function when webpack-dev-server starts ```javascript module.exports = { - //... + // ... devServer: { - onListening: function (devServer) { + onListening (devServer) { if (!devServer) { throw new Error("webpack-dev-server is not defined"); } - const port = devServer.server.address().port; + const {port} = devServer.server.address(); console.log("Listening on port:", port); }, }, @@ -1171,7 +1169,7 @@ Tells dev-server to open the browser after server had been started. Set it to `t ```javascript module.exports = { - //... + // ... devServer: { open: true, }, @@ -1196,7 +1194,7 @@ To open a specified page in a browser: ```javascript module.exports = { - //... + // ... devServer: { open: ["/my-page"], }, @@ -1215,7 +1213,7 @@ To open multiple specified pages in browser: ```javascript module.exports = { - //... + // ... devServer: { open: ["/my-page", "/another-page"], }, @@ -1234,7 +1232,7 @@ Provide browser name to use instead of the default one: ```javascript module.exports = { - //... + // ... devServer: { open: { app: { @@ -1257,7 +1255,7 @@ The object accepts all [open](https://www.npmjs.com/package/open) options: ```javascript module.exports = { - //... + // ... devServer: { open: { target: ["first.html", "http://localhost:8080/second.html"], @@ -1284,7 +1282,7 @@ Specify a port number to listen for requests on: ```javascript module.exports = { - //... + // ... devServer: { port: 8080, }, @@ -1303,7 +1301,7 @@ npx webpack serve --port 8080 ```javascript module.exports = { - //... + // ... devServer: { port: "auto", }, @@ -1330,7 +1328,7 @@ With a backend on `localhost:3000`, you can use this to enable proxying: ```javascript module.exports = { - //... + // ... devServer: { proxy: { "/api": "http://localhost:3000", @@ -1347,7 +1345,7 @@ If you don't want `/api` to be passed along, we need to rewrite the path: ```javascript module.exports = { - //... + // ... devServer: { proxy: { "/api": { @@ -1365,7 +1363,7 @@ A backend server running on HTTPS with an invalid certificate will not be accept ```javascript module.exports = { - //... + // ... devServer: { proxy: { "/api": { @@ -1391,13 +1389,13 @@ E.g. for a browser request, you want to serve an HTML page, but for an API reque ```javascript module.exports = { - //... + // ... devServer: { proxy: { "/api": { target: "http://localhost:3000", - bypass: function (req, res, proxyOptions) { - if (req.headers.accept.indexOf("html") !== -1) { + bypass (req, res, proxyOptions) { + if (req.headers.accept.includes("html")) { console.log("Skipping proxy for browser request."); return "/index.html"; } @@ -1414,7 +1412,7 @@ If you want to proxy multiple, specific paths to the same target, you can use an ```javascript module.exports = { - //... + // ... devServer: { proxy: [ { @@ -1432,7 +1430,7 @@ Note that requests to root won't be proxied by default. To enable root proxying, ```javascript module.exports = { - //... + // ... devServer: { devMiddleware: { index: false, // specify to enable root proxying @@ -1451,7 +1449,7 @@ The origin of the host header is kept when proxying by default, you can set `cha ```javascript module.exports = { - //... + // ... devServer: { proxy: { "/api": { @@ -1475,7 +1473,7 @@ Allows to set server and options (by default 'http'). ```javascript module.exports = { - //... + // ... devServer: { server: "http", }, @@ -1494,7 +1492,7 @@ To serve over `HTTPS` with a self-signed certificate: ```javascript module.exports = { - //... + // ... devServer: { server: "https", }, @@ -1513,7 +1511,7 @@ To serve over `HTTP/2` using [spdy](https://www.npmjs.com/package/spdy) with a s ```javascript module.exports = { - //... + // ... devServer: { server: "spdy", }, @@ -1536,7 +1534,7 @@ Use the object syntax to provide your own certificate: ```javascript module.exports = { - //... + // ... devServer: { server: { type: "https", @@ -1564,11 +1562,11 @@ It also allows you to set additional [TLS options](https://nodejs.org/api/tls.ht **webpack.config.js** ```javascript -const fs = require("fs"); -const path = require("path"); +const fs = require("node:fs"); +const path = require("node:path"); module.exports = { - //... + // ... devServer: { server: { type: "https", @@ -1600,7 +1598,7 @@ Allows to close dev server and exit the process on `SIGINT` and `SIGTERM` signal ```javascript module.exports = { - //... + // ... devServer: { setupExitSignals: true, }, @@ -1672,7 +1670,7 @@ This option allows configuring options for serving static files from the directo ```javascript module.exports = { - //... + // ... devServer: { static: false, }, @@ -1738,10 +1736,10 @@ Tell the server where to serve the content from. This is only necessary if you w **webpack.config.js** ```javascript -const path = require("path"); +const path = require("node:path"); module.exports = { - //... + // ... devServer: { static: { directory: path.join(__dirname, "public"), @@ -1755,10 +1753,10 @@ Provide an array of objects in case you have multiple static folders: **webpack.config.js** ```javascript -const path = require("path"); +const path = require("node:path"); module.exports = { - //... + // ... devServer: { static: [ { @@ -1786,7 +1784,7 @@ It is possible to configure advanced options for serving static files from [`sta ```javascript module.exports = { - //... + // ... devServer: { static: { staticOptions: { @@ -1806,10 +1804,10 @@ Tell the server at which URL to serve [`static.directory`](#directory) content. **webpack.config.js** ```javascript -const path = require("path"); +const path = require("node:path"); module.exports = { - //... + // ... devServer: { static: { directory: path.join(__dirname, "assets"), @@ -1824,10 +1822,10 @@ Provide an array of objects in case you have multiple static folders: **webpack.config.js** ```javascript -const path = require("path"); +const path = require("node:path"); module.exports = { - //... + // ... devServer: { static: [ { @@ -1854,10 +1852,10 @@ Tell dev-server to use [`serveIndex`](https://github.com/expressjs/serve-index) **webpack.config.js** ```javascript -const path = require("path"); +const path = require("node:path"); module.exports = { - //... + // ... devServer: { static: { directory: path.join(__dirname, "public"), @@ -1888,10 +1886,10 @@ Tell dev-server to watch the files served by the [`static.directory`](#directory **webpack.config.js** ```javascript -const path = require("path"); +const path = require("node:path"); module.exports = { - //... + // ... devServer: { static: { directory: path.join(__dirname, "public"), @@ -1918,10 +1916,10 @@ It is possible to configure advanced options for watching static files from [`st **webpack.config.js** ```javascript -const path = require("path"); +const path = require("node:path"); module.exports = { - //... + // ... devServer: { static: { directory: path.join(__dirname, "public"), @@ -1944,7 +1942,7 @@ This option allows you to configure a list of globs/directories/files to watch f ```javascript module.exports = { - //... + // ... devServer: { watchFiles: ["src/**/*.php", "public/**/*"], }, @@ -1957,7 +1955,7 @@ It is possible to configure advanced options for watching files. See the [`choki ```javascript module.exports = { - //... + // ... devServer: { watchFiles: { paths: ["src/**/*.php", "public/**/*"], @@ -1981,7 +1979,7 @@ The current default mode is `'ws'`. This mode uses [`ws`](https://www.npmjs.com/ ```javascript module.exports = { - //... + // ... devServer: { webSocketServer: "ws", }, @@ -1996,7 +1994,7 @@ Using path to `CustomServer.js`, a custom WebSocket server implementation, along ```javascript module.exports = { - //... + // ... devServer: { client: { webSocketTransport: "ws", @@ -2012,7 +2010,7 @@ Using custom, compatible WebSocket client and server implementations: ```javascript module.exports = { - //... + // ... devServer: { client: { webSocketTransport: require.resolve("./CustomClient"), diff --git a/README.md b/README.md index e8ceea5f5f..d0d49ae267 100644 --- a/README.md +++ b/README.md @@ -229,7 +229,7 @@ If you use TypeScript in the webpack config, you'll need to properly type `devSe ```ts /// -import type { Configuration } from "webpack"; +import { type Configuration } from "webpack"; // Your logic ``` @@ -237,8 +237,8 @@ import type { Configuration } from "webpack"; Or you can import the type from `webpack-dev-server`, i.e. ```ts -import type { Configuration as DevServerConfiguration } from "webpack-dev-server"; -import type { Configuration } from "webpack"; +import { type Configuration } from "webpack"; +import { type Configuration as DevServerConfiguration } from "webpack-dev-server"; const devServer: DevServerConfiguration = {}; const config: Configuration = { devServer }; diff --git a/bin/webpack-dev-server.js b/bin/webpack-dev-server.js index 7effdca89f..ede7e84215 100755 --- a/bin/webpack-dev-server.js +++ b/bin/webpack-dev-server.js @@ -10,7 +10,8 @@ * @returns {Promise} promise */ const runCommand = (command, args) => { - const cp = require("child_process"); + const cp = require("node:child_process"); + return new Promise((resolve, reject) => { const executedCommand = cp.spawn(command, args, { stdio: "inherit", @@ -40,7 +41,7 @@ const isInstalled = (packageName) => { return true; } - const path = require("path"); + const path = require("node:path"); const fs = require("graceful-fs"); let dir = __dirname; @@ -52,20 +53,19 @@ const isInstalled = (packageName) => { ) { return true; } - } catch (_error) { + } catch { // Nothing } - // eslint-disable-next-line no-cond-assign } while (dir !== (dir = path.dirname(dir))); // https://github.com/nodejs/node/blob/v18.9.1/lib/internal/modules/cjs/loader.js#L1274 // @ts-ignore - for (const internalPath of require("module").globalPaths) { + for (const internalPath of require("node:module").globalPaths) { try { if (fs.statSync(path.join(internalPath, packageName)).isDirectory()) { return true; } - } catch (_error) { + } catch { // Nothing } } @@ -81,9 +81,11 @@ const runCli = (cli) => { if (cli.preprocess) { cli.preprocess(); } - const path = require("path"); + + const path = require("node:path"); + const pkgPath = require.resolve(`${cli.package}/package.json`); - // eslint-disable-next-line import/no-dynamic-require + const pkg = require(pkgPath); if (pkg.type === "module" || /\.mjs/i.test(pkg.bin[cli.binName])) { @@ -94,19 +96,18 @@ const runCli = (cli) => { }, ); } else { - // eslint-disable-next-line import/no-dynamic-require require(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName])); } }; /** - * @typedef {Object} CliOption + * @typedef {object} CliOption * @property {string} name display name * @property {string} package npm package name * @property {string} binName name of the executable file * @property {boolean} installed currently installed? * @property {string} url homepage - * @property {function} preprocess preprocessor + * @property {Function} preprocess preprocessor */ /** @type {CliOption} */ @@ -122,9 +123,9 @@ const cli = { }; if (!cli.installed) { - const path = require("path"); + const path = require("node:path"); const fs = require("graceful-fs"); - const readLine = require("readline"); + const readLine = require("node:readline"); const notify = `CLI for webpack must be installed.\n ${cli.name} (${cli.url})\n`; @@ -151,7 +152,7 @@ if (!cli.installed) { )} ${cli.package}".`, ); - const question = `Do you want to install 'webpack-cli' (yes/no): `; + const question = "Do you want to install 'webpack-cli' (yes/no): "; const questionInterface = readLine.createInterface({ input: process.stdin, diff --git a/client-src/webpack.config.js b/client-src/webpack.config.js index 333f50a20c..210f775f5c 100644 --- a/client-src/webpack.config.js +++ b/client-src/webpack.config.js @@ -1,6 +1,6 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const webpack = require("webpack"); const { merge } = require("webpack-merge"); diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000000..149a56f73b --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,22 @@ +import { defineConfig } from "eslint/config"; +import config from "eslint-config-webpack"; + +export default defineConfig([ + { + ignores: ["client/**/*", "types/**/*", "examples/**/main.js", "examples/client/trusted-types-overlay/app.js"] + }, + { + extends: [config], + }, + { + files: ["test/**/*"], + rules: { + "jsdoc/require-jsdoc": "off", + "jsdoc/require-returns": "off", + "jsdoc/require-param-description": "off", + "jsdoc/require-param-type": "off", + "jsdoc/require-property-description": "off", + "jsdoc/require-returns-description": "off", + } + } +]); diff --git a/examples/api/simple/app.js b/examples/api/simple/app.js index c08e6931f6..550a73c229 100644 --- a/examples/api/simple/app.js +++ b/examples/api/simple/app.js @@ -6,7 +6,7 @@ target.classList.add("pass"); target.innerHTML = "Success!"; // This results in a warning: -if (!window) { +if (!globalThis) { // eslint-disable-next-line require(`./${window}parseable.js`); } diff --git a/examples/app/hono/webpack.config.js b/examples/app/hono/webpack.config.js index acd032e4b8..dff0e98988 100644 --- a/examples/app/hono/webpack.config.js +++ b/examples/app/hono/webpack.config.js @@ -1,10 +1,10 @@ "use strict"; -const wdm = require("webpack-dev-middleware"); -const { Hono } = require("hono"); const { createAdaptorServer } = require("@hono/node-server"); -// eslint-disable-next-line import/extensions, import/no-unresolved +// eslint-disable-next-line import/no-unresolved const { serveStatic } = require("@hono/node-server/serve-static"); +const { Hono } = require("hono"); +const wdm = require("webpack-dev-middleware"); const { setup } = require("../../util"); // our setup function adds behind-the-scenes bits to the config that all of our diff --git a/examples/client/overlay/app.js b/examples/client/overlay/app.js index 66ea41f70d..0303b0653f 100644 --- a/examples/client/overlay/app.js +++ b/examples/client/overlay/app.js @@ -1,6 +1,5 @@ "use strict"; -// eslint-disable-next-line import/order const createButton = require("./create-button"); /** diff --git a/examples/client/overlay/create-button.js b/examples/client/overlay/create-button.js index e37bdb62b7..4631083de9 100644 --- a/examples/client/overlay/create-button.js +++ b/examples/client/overlay/create-button.js @@ -1,7 +1,6 @@ "use strict"; /** - * * @param {string} label * @param {() => void} onClick * @returns HTMLButtonElement diff --git a/examples/client/trusted-types-overlay/webpack.config.js b/examples/client/trusted-types-overlay/webpack.config.js index 7399f26646..af962f1ff8 100644 --- a/examples/client/trusted-types-overlay/webpack.config.js +++ b/examples/client/trusted-types-overlay/webpack.config.js @@ -1,6 +1,6 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); // our setup function adds behind-the-scenes bits to the config that all of our // examples need diff --git a/examples/general/proxy-hot-reload/proxy-config.js b/examples/general/proxy-hot-reload/proxy-config.js index 62c787bba1..f023c51ffb 100644 --- a/examples/general/proxy-hot-reload/proxy-config.js +++ b/examples/general/proxy-hot-reload/proxy-config.js @@ -13,8 +13,10 @@ module.exports = { // Replace it with following and save the file: // -/** / -module.exports = { - target: 'http://reqres.in/' -}; -/**/ +/** + * / + * module.exports = { + * target: 'http://reqres.in/' + * }; + * /* + */ diff --git a/examples/general/proxy-hot-reload/webpack.config.js b/examples/general/proxy-hot-reload/webpack.config.js index 87c8312762..50e4530a23 100644 --- a/examples/general/proxy-hot-reload/webpack.config.js +++ b/examples/general/proxy-hot-reload/webpack.config.js @@ -1,6 +1,6 @@ "use strict"; -const fs = require("fs"); +const fs = require("node:fs"); // our setup function adds behind-the-scenes bits to the config that all of our // examples need const { setup } = require("../../util"); @@ -17,6 +17,7 @@ fs.watch("./proxy-config.js", () => { delete require.cache[require.resolve("./proxy-config")]; try { const newProxyConfig = require("./proxy-config"); + if (proxyOptions.target !== newProxyConfig.target) { console.log("Proxy target changed:", newProxyConfig.target); proxyOptions = { @@ -26,7 +27,7 @@ fs.watch("./proxy-config.js", () => { changeOrigin: true, }; } - } catch (e) { + } catch { // ignore } }); diff --git a/examples/general/universal-config/client.js b/examples/general/universal-config/client.js index 0656b3449f..bfae6682f6 100644 --- a/examples/general/universal-config/client.js +++ b/examples/general/universal-config/client.js @@ -2,7 +2,7 @@ const target = document.querySelector("#target"); -if (!window.fetch) { +if (!globalThis.fetch) { target.classList.add("fail"); target.innerHTML = "fetch is not supported"; } else { @@ -18,8 +18,8 @@ if (!window.fetch) { target.innerHTML = "[client.js, server.js]: Success!"; } }) - .catch((e) => { + .catch((err) => { target.classList.add("fail"); - target.innerHTML = e.message; + target.innerHTML = err.message; }); } diff --git a/examples/general/webworker/worker.js b/examples/general/webworker/worker.js index febf315aae..d799292230 100644 --- a/examples/general/webworker/worker.js +++ b/examples/general/webworker/worker.js @@ -2,7 +2,7 @@ /* eslint-env worker */ -self.onmessage = function onMessage(e) { +globalThis.onmessage = function onMessage(e) { console.log("[WORKER]", e); self.postMessage({ hello: 222, diff --git a/examples/headers/function/README.md b/examples/headers/function/README.md index b6f9c65daf..e871f76714 100644 --- a/examples/headers/function/README.md +++ b/examples/headers/function/README.md @@ -8,9 +8,7 @@ Adds headers to all responses. module.exports = { // ... devServer: { - headers: () => { - return { "X-Custom-Header": ["key1=value1", "key2=value2"] }; - }, + headers: () => ({ "X-Custom-Header": ["key1=value1", "key2=value2"] }), }, }; ``` diff --git a/examples/headers/function/webpack.config.js b/examples/headers/function/webpack.config.js index 2e24161575..9ae00dcd3d 100644 --- a/examples/headers/function/webpack.config.js +++ b/examples/headers/function/webpack.config.js @@ -8,8 +8,6 @@ module.exports = setup({ context: __dirname, entry: "./app.js", devServer: { - headers: () => { - return { "X-Custom-Header": ["key1=value1", "key2=value2"] }; - }, + headers: () => ({ "X-Custom-Header": ["key1=value1", "key2=value2"] }), }, }); diff --git a/examples/history-api-fallback/app.js b/examples/history-api-fallback/app.js index 62c978c7d9..d940d46306 100644 --- a/examples/history-api-fallback/app.js +++ b/examples/history-api-fallback/app.js @@ -54,7 +54,7 @@ document.addEventListener( table.appendChild(tbody); target.parentNode.appendChild(table); - tests.forEach((test) => { + for (const test of tests) { const tr = document.createElement("tr"); tbody.appendChild(tr); check(test.url, test.re, (res) => { @@ -62,11 +62,16 @@ document.addEventListener( tr.innerHTML += `${test.url}`; tr.innerHTML += `${res}`; }); - }); + } }, true, ); +/** + * @param url + * @param re + * @param cb + */ function check(url, re, cb) { const xhr = new XMLHttpRequest(); xhr.addEventListener("load", () => { diff --git a/examples/ipc/README.md b/examples/ipc/README.md index 6d99d80430..0379ec03ac 100644 --- a/examples/ipc/README.md +++ b/examples/ipc/README.md @@ -30,7 +30,7 @@ You can also listen to a different socket with: **webpack.config.js** ```js -const path = require("path"); +const path = require("node:path"); module.exports = { // ... diff --git a/examples/ipc/webpack.config.js b/examples/ipc/webpack.config.js index e8543d97fe..ea85092a65 100644 --- a/examples/ipc/webpack.config.js +++ b/examples/ipc/webpack.config.js @@ -1,6 +1,6 @@ "use strict"; -const http = require("http"); +const http = require("node:http"); const httpProxy = require("http-proxy"); // our setup function adds behind-the-scenes bits to the config that all of our // examples need diff --git a/examples/on-listening/README.md b/examples/on-listening/README.md index fff5fc2a6b..c991b752b9 100644 --- a/examples/on-listening/README.md +++ b/examples/on-listening/README.md @@ -9,7 +9,7 @@ module.exports = { // ... devServer: { onListening: (devServer) => { - const port = devServer.server.address().port; + const {port} = devServer.server.address(); console.log("Listening on port:", port); }, }, diff --git a/examples/on-listening/webpack.config.js b/examples/on-listening/webpack.config.js index 74cc6320c4..8c9481746d 100644 --- a/examples/on-listening/webpack.config.js +++ b/examples/on-listening/webpack.config.js @@ -9,7 +9,7 @@ module.exports = setup({ entry: "./app.js", devServer: { onListening: (devServer) => { - const port = devServer.server.address().port; + const { port } = devServer.server.address(); console.log("Listening on port:", port); }, }, diff --git a/examples/open-target-multiple/app1.js b/examples/open-target-multiple/app1.js index ebef30052b..09a8c2b001 100644 --- a/examples/open-target-multiple/app1.js +++ b/examples/open-target-multiple/app1.js @@ -2,7 +2,7 @@ const target = document.querySelector("#target"); -if (window.location.href.endsWith("example1.html")) { +if (globalThis.location.href.endsWith("example1.html")) { target.classList.add("pass"); target.innerHTML = "Success!"; } else { diff --git a/examples/open-target-multiple/app2.js b/examples/open-target-multiple/app2.js index 97d45eb054..69297e2b2b 100644 --- a/examples/open-target-multiple/app2.js +++ b/examples/open-target-multiple/app2.js @@ -2,7 +2,7 @@ const target = document.querySelector("#target"); -if (window.location.href.endsWith("example2.html")) { +if (globalThis.location.href.endsWith("example2.html")) { target.classList.add("pass"); target.innerHTML = "Success!"; } else { diff --git a/examples/open-target/app.js b/examples/open-target/app.js index c18dc29b7c..7d91e11582 100644 --- a/examples/open-target/app.js +++ b/examples/open-target/app.js @@ -2,7 +2,7 @@ const target = document.querySelector("#target"); -if (window.location.href.endsWith("example.html#page1")) { +if (globalThis.location.href.endsWith("example.html#page1")) { target.classList.add("pass"); target.innerHTML = "Success!"; } else { diff --git a/examples/proxy/webpack.config.js b/examples/proxy/webpack.config.js index 83c03f5f8c..0b550270a2 100644 --- a/examples/proxy/webpack.config.js +++ b/examples/proxy/webpack.config.js @@ -5,6 +5,9 @@ const express = require("express"); // examples need const { setup } = require("../util"); +/** + * + */ async function listenProxyServer() { const proxyApp = express(); diff --git a/examples/server/https/README.md b/examples/server/https/README.md index f26fdc5e91..bf49244f73 100644 --- a/examples/server/https/README.md +++ b/examples/server/https/README.md @@ -39,8 +39,8 @@ npx webpack serve --open --server-type https --server-options-key ./ssl/server.k You can also directly pass the contents of respective files: ```js -const fs = require("fs"); -const path = require("path"); +const fs = require("node:fs"); +const path = require("node:path"); module.exports = { // ... diff --git a/examples/util.js b/examples/util.js index 633939d890..fbf0133dda 100644 --- a/examples/util.js +++ b/examples/util.js @@ -2,11 +2,11 @@ /* eslint-disable import/no-extraneous-dependencies */ -const path = require("path"); +const path = require("node:path"); const fs = require("graceful-fs"); -const mime = require("mime"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const { marked } = require("marked"); +const mime = require("mime"); module.exports = { setup(config) { @@ -18,9 +18,9 @@ module.exports = { } else if (Array.isArray(config.entry)) { config.entry = config.entry.map((entry) => path.resolve(entry)); } else if (typeof config.entry === "object") { - Object.entries(config.entry).forEach(([key, value]) => { + for (const [key, value] of Object.entries(config.entry)) { config.entry[key] = path.resolve(value); - }); + } } } @@ -41,7 +41,7 @@ module.exports = { }); }; const renderer = new marked.Renderer(); - const heading = renderer.heading; + const { heading } = renderer; const markedOptions = { gfm: true, tables: true, @@ -58,7 +58,7 @@ module.exports = { renderer, xhtml: false, }; - const readme = fs.readFileSync("README.md", "utf-8"); + const readme = fs.readFileSync("README.md", "utf8"); let exampleTitle = ""; @@ -99,11 +99,7 @@ module.exports = { path: path.dirname(module.parent.filename), }; - if (result.output) { - result.output = { ...result.output, ...output }; - } else { - result.output = output; - } + result.output = result.output ? { ...result.output, ...output } : output; return result; }, diff --git a/lib/Server.js b/lib/Server.js index 49906ece2a..def7121652 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -1,9 +1,9 @@ "use strict"; -const os = require("os"); -const path = require("path"); -const url = require("url"); -const util = require("util"); +const os = require("node:os"); +const path = require("node:path"); +const url = require("node:url"); +const util = require("node:util"); const fs = require("graceful-fs"); const ipaddr = require("ipaddr.js"); const { validate } = require("schema-utils"); @@ -31,7 +31,7 @@ const schema = require("./options.json"); /** @typedef {import("ipaddr.js").IPv4} IPv4 */ /** @typedef {import("ipaddr.js").IPv6} IPv6 */ /** @typedef {import("net").Socket} Socket */ -/** @typedef {import("http").Server} HTTPServer*/ +/** @typedef {import("http").Server} HTTPServer */ /** @typedef {import("http").IncomingMessage} IncomingMessage */ /** @typedef {import("http").ServerResponse} ServerResponse */ /** @typedef {import("open").Options} OpenOptions */ @@ -79,13 +79,13 @@ const schema = require("./options.json"); */ /** - * @typedef {Object} WatchFiles + * @typedef {object} WatchFiles * @property {string | string[]} paths * @property {WatchOptions & { aggregateTimeout?: number, ignored?: WatchOptions["ignored"], poll?: number | boolean }} [options] */ /** - * @typedef {Object} Static + * @typedef {object} Static * @property {string} [directory] * @property {string | string[]} [publicPath] * @property {boolean | ServeIndexOptions} [serveIndex] @@ -94,7 +94,7 @@ const schema = require("./options.json"); */ /** - * @typedef {Object} NormalizedStatic + * @typedef {object} NormalizedStatic * @property {string} directory * @property {string[]} publicPath * @property {false | ServeIndexOptions} serveIndex @@ -111,13 +111,13 @@ const schema = require("./options.json"); /** * @template {BasicApplication} [A=ExpressApplication] * @template {BasicServer} [S=import("http").Server] - * @typedef {Object} ServerConfiguration + * @typedef {object} ServerConfiguration * @property {ServerType} [type] * @property {ServerOptions} [options] */ /** - * @typedef {Object} WebSocketServerConfiguration + * @typedef {object} WebSocketServerConfiguration * @property {"sockjs" | "ws" | string | Function} [type] * @property {Record} [options] */ @@ -150,25 +150,25 @@ const schema = require("./options.json"); */ /** - * @typedef {Object} OpenApp + * @typedef {object} OpenApp * @property {string} [name] * @property {string[]} [arguments] */ /** - * @typedef {Object} Open + * @typedef {object} Open * @property {string | string[] | OpenApp} [app] * @property {string | string[]} [target] */ /** - * @typedef {Object} NormalizedOpen + * @typedef {object} NormalizedOpen * @property {string} target * @property {import("open").Options} options */ /** - * @typedef {Object} WebSocketURL + * @typedef {object} WebSocketURL * @property {string} [hostname] * @property {string} [password] * @property {string} [pathname] @@ -182,7 +182,7 @@ const schema = require("./options.json"); */ /** - * @typedef {Object} ClientConfiguration + * @typedef {object} ClientConfiguration * @property {"log" | "info" | "warn" | "error" | "none" | "verbose"} [logging] * @property {boolean | { warnings?: OverlayMessageOptions, errors?: OverlayMessageOptions, runtimeErrors?: OverlayMessageOptions }} [overlay] * @property {boolean} [progress] @@ -213,7 +213,7 @@ const schema = require("./options.json"); /** * @template {BasicApplication} [A=ExpressApplication] * @template {BasicServer} [S=import("http").Server] - * @typedef {Object} Configuration + * @typedef {object} Configuration * @property {boolean | string} [ipc] * @property {Host} [host] * @property {Port} [port] @@ -261,7 +261,7 @@ const memoize = (fn) => { cache = true; // Allow to clean up memory for fn // and all dependent resources - // eslint-disable-next-line no-undefined + fn = undefined; return result; @@ -271,7 +271,6 @@ const memoize = (fn) => { const getExpress = memoize(() => require("express")); /** - * * @param {OverlayMessageOptions} [setting] * @returns */ @@ -310,7 +309,7 @@ function useFn(route, fn) { const DEFAULT_ALLOWED_PROTOCOLS = /^(file|.+-extension):/i; /** - * @typedef {Object} BasicApplication + * @typedef {object} BasicApplication * @property {typeof useFn} use */ @@ -332,7 +331,7 @@ class Server { this.compiler = compiler; /** * @type {ReturnType} - * */ + */ this.logger = this.compiler.getInfrastructureLogger("webpack-dev-server"); this.options = options; /** @@ -358,7 +357,7 @@ class Server { * @private * @type {string | undefined} */ - // eslint-disable-next-line no-undefined + this.currentHash = undefined; } @@ -406,7 +405,7 @@ class Server { let host; const networks = Object.values(os.networkInterfaces()) - // eslint-disable-next-line no-shadow + .flatMap((networks) => networks ?? []) .filter((network) => { if (!network || !network.address) { @@ -518,17 +517,19 @@ class Server { } const pRetry = (await import("p-retry")).default; + const getPort = require("./getPort"); + const basePort = typeof process.env.WEBPACK_DEV_SERVER_BASE_PORT !== "undefined" - ? parseInt(process.env.WEBPACK_DEV_SERVER_BASE_PORT, 10) + ? Number.parseInt(process.env.WEBPACK_DEV_SERVER_BASE_PORT, 10) : 8080; // Try to find unused port and listen on it for 3 times, // if port is not specified in options. const defaultPortRetry = typeof process.env.WEBPACK_DEV_SERVER_PORT_RETRY !== "undefined" - ? parseInt(process.env.WEBPACK_DEV_SERVER_PORT_RETRY, 10) + ? Number.parseInt(process.env.WEBPACK_DEV_SERVER_PORT_RETRY, 10) : 3; return pRetry(() => getPort(basePort, host), { @@ -551,12 +552,11 @@ class Server { try { if (fs.statSync(path.join(dir, "package.json")).isFile()) break; // eslint-disable-next-line no-empty - } catch (e) {} + } catch {} const parent = path.dirname(dir); if (dir === parent) { - // eslint-disable-next-line no-undefined dir = undefined; break; } @@ -607,7 +607,7 @@ class Server { "electron-renderer", "nwjs", "node-webkit", - // eslint-disable-next-line no-undefined + undefined, null, ]; @@ -810,7 +810,6 @@ class Server { // use a hook to add entries if available for (const additionalEntry of additionalEntries) { new webpack.EntryPlugin(compiler.context, additionalEntry, { - // eslint-disable-next-line no-undefined name: undefined, }).apply(compiler); } @@ -854,7 +853,7 @@ class Server { "electron-preload", "electron-renderer", "node-webkit", - // eslint-disable-next-line no-undefined + undefined, null, ].includes(/** @type {string} */ (config.options.target)), @@ -937,15 +936,13 @@ class Server { * @returns {NormalizedStatic} */ const getStaticItem = (optionsForStatic) => { - const getDefaultStaticOptions = () => { - return { - directory: path.join(process.cwd(), "public"), - staticOptions: {}, - publicPath: ["/"], - serveIndex: { icons: true }, - watch: getWatchOptions(), - }; - }; + const getDefaultStaticOptions = () => ({ + directory: path.join(process.cwd(), "public"), + staticOptions: {}, + publicPath: ["/"], + serveIndex: { icons: true }, + watch: getWatchOptions(), + }); /** @type {NormalizedStatic} */ let item; @@ -970,7 +967,6 @@ class Server { ? { ...def.staticOptions, ...optionsForStatic.staticOptions } : def.staticOptions, publicPath: - // eslint-disable-next-line no-nested-ternary typeof optionsForStatic.publicPath !== "undefined" ? Array.isArray(optionsForStatic.publicPath) ? optionsForStatic.publicPath @@ -982,10 +978,9 @@ class Server { // If 'serveIndex' is an object, merge its properties with default 'serveIndex' // If 'serveIndex' is neither a boolean true nor an object, use it as-is // If 'serveIndex' is not defined in 'optionsForStatic', use default 'serveIndex' - // eslint-disable-next-line no-nested-ternary + typeof optionsForStatic.serveIndex !== "undefined" - ? // eslint-disable-next-line no-nested-ternary - typeof optionsForStatic.serveIndex === "boolean" && + ? typeof optionsForStatic.serveIndex === "boolean" && optionsForStatic.serveIndex ? def.serveIndex : typeof optionsForStatic.serveIndex === "object" @@ -993,10 +988,8 @@ class Server { : optionsForStatic.serveIndex : def.serveIndex, watch: - // eslint-disable-next-line no-nested-ternary typeof optionsForStatic.watch !== "undefined" - ? // eslint-disable-next-line no-nested-ternary - typeof optionsForStatic.watch === "boolean" + ? typeof optionsForStatic.watch === "boolean" ? optionsForStatic.watch ? def.watch : false @@ -1161,7 +1154,6 @@ class Server { for (const property of httpsProperties) { if (typeof serverOptions[property] === "undefined") { - // eslint-disable-next-line no-continue continue; } @@ -1184,7 +1176,7 @@ class Server { try { stats = fs.lstatSync(fs.realpathSync(item)).isFile(); - } catch (error) { + } catch { // Ignore error } @@ -1216,7 +1208,7 @@ class Server { if (certificateExists) { const certificateTtl = 1000 * 60 * 60 * 24; const certificateStat = await fs.promises.stat(certificatePath); - const now = Number(new Date()); + const now = Date.now(); // cert is more than 30 days old, kill it with fire if ((now - Number(certificateStat.ctime)) / certificateTtl > 30) { @@ -1234,6 +1226,7 @@ class Server { this.logger.info("Generating SSL certificate..."); const selfsigned = require("selfsigned"); + const attributes = [{ name: "commonName", value: "localhost" }]; const pems = selfsigned.generate(attributes, { algorithm: "sha256", @@ -1346,9 +1339,10 @@ class Server { const normalizedTarget = typeof target === "undefined" ? "" : target; if (Array.isArray(normalizedTarget)) { - return normalizedTarget.map((singleTarget) => { - return { target: singleTarget, options: normalizedOptions }; - }); + return normalizedTarget.map((singleTarget) => ({ + target: singleTarget, + options: normalizedOptions, + })); } return [{ target: normalizedTarget, options: normalizedOptions }]; @@ -1379,7 +1373,7 @@ class Server { for (const item of options.open) { if (typeof item === "string") { result.push({ target: item, options: defaultOpenOptions }); - // eslint-disable-next-line no-continue + continue; } @@ -1594,7 +1588,7 @@ class Server { } else { try { clientImplementation = require.resolve(clientTransport); - } catch (e) { + } catch { clientImplementationFound = false; } } @@ -1647,12 +1641,11 @@ class Server { implementation = require("./servers/WebsocketServer"); } else { try { - // eslint-disable-next-line import/no-dynamic-require implementation = require( /** @type {WebSocketServerConfiguration} */ (this.options.webSocketServer).type, ); - } catch (error) { + } catch { implementationFound = false; } } @@ -1680,7 +1673,7 @@ class Server { /** * @returns {string} */ - // eslint-disable-next-line class-methods-use-this + getClientEntry() { return require.resolve("../client/index.js"); } @@ -1702,10 +1695,10 @@ class Server { */ setupProgressPlugin() { const { ProgressPlugin } = - /** @type {MultiCompiler}*/ + /** @type {MultiCompiler} */ (this.compiler).compilers - ? /** @type {MultiCompiler}*/ (this.compiler).compilers[0].webpack - : /** @type {Compiler}*/ (this.compiler).webpack; + ? /** @type {MultiCompiler} */ (this.compiler).compilers[0].webpack + : /** @type {Compiler} */ (this.compiler).webpack; new ProgressPlugin( /** @@ -1757,7 +1750,6 @@ class Server { for (const compiler of compilers) { if (compiler.options.devServer === false) { - // eslint-disable-next-line no-continue continue; } @@ -1776,7 +1768,7 @@ class Server { if (HMRPluginExists) { this.logger.warn( - `"hot: true" automatically applies HMR plugin, you don't have to add it manually to your webpack configuration.`, + '"hot: true" automatically applies HMR plugin, you don\'t have to add it manually to your webpack configuration.', ); } else { // Apply the HMR plugin @@ -1804,7 +1796,7 @@ class Server { let needForceShutdown = false; - signals.forEach((signal) => { + for (const signal of signals) { const listener = () => { if (needForceShutdown) { process.exit(); @@ -1830,7 +1822,7 @@ class Server { this.listeners.push({ name: signal, listener }); process.on(signal, listener); - }); + } } // Proxy WebSocket without the initial http request @@ -1854,7 +1846,7 @@ class Server { * @returns {Promise} */ async setupApp() { - /** @type {A | undefined}*/ + /** @type {A | undefined} */ this.app = typeof this.options.app === "function" ? await this.options.app() @@ -2081,7 +2073,7 @@ class Server { try { // TODO implement `inputFileSystem.createReadStream` in webpack stats = fs.statSync(clientPath); - } catch (err) { + } catch { next(); return; } @@ -2196,13 +2188,12 @@ class Server { (/** @type {MultiStats} */ (stats).toJson().children) : [/** @type {Stats} */ (stats).toJson()]; - res.write(`

Assets Report:

`); + res.write("

Assets Report:

"); for (const [index, item] of statsForPrint.entries()) { res.write("
"); const name = - // eslint-disable-next-line no-nested-ternary typeof item.name !== "undefined" ? item.name : /** @type {MultiStats} */ (stats).stats @@ -2287,7 +2278,7 @@ class Server { * } * ] */ - this.options.proxy.forEach((proxyConfigOrCallback) => { + for (const proxyConfigOrCallback of this.options.proxy) { /** * @type {RequestHandler} */ @@ -2387,7 +2378,7 @@ class Server { */ (error, req, res, next) => handler(req, res, next), }); - }); + } middlewares.push({ name: "webpack-dev-middleware", @@ -2416,6 +2407,7 @@ class Server { if (this.options.historyApiFallback) { const connectHistoryApiFallback = require("connect-history-api-fallback"); + const { historyApiFallback } = this.options; if ( @@ -2585,7 +2577,7 @@ class Server { (this.options.server); if (typeof type === "function") { - /** @type {S | undefined}*/ + /** @type {S | undefined} */ this.server = await type( /** @type {ServerOptions} */ (options), @@ -2593,10 +2585,9 @@ class Server { (this.app), ); } else { - // eslint-disable-next-line import/no-dynamic-require const serverType = require(/** @type {string} */ (type)); - /** @type {S | undefined}*/ + /** @type {S | undefined} */ this.server = type === "http2" ? serverType.createSecureServer( @@ -2658,7 +2649,6 @@ class Server { (client, request) => { /** @type {{ [key: string]: string | undefined } | undefined} */ const headers = - // eslint-disable-next-line no-nested-ternary typeof request !== "undefined" ? /** @type {{ [key: string]: string | undefined }} */ (request.headers) @@ -2666,8 +2656,7 @@ class Server { /** @type {import("sockjs").Connection} */ (client).headers ) !== "undefined" ? /** @type {import("sockjs").Connection} */ (client).headers - : // eslint-disable-next-line no-undefined - undefined; + : undefined; if (!headers) { this.logger.warn( @@ -2816,6 +2805,7 @@ class Server { */ runBonjour() { const { Bonjour } = require("bonjour-service"); + const type = this.isTlsServer ? "https" : "http"; /** @@ -2833,6 +2823,7 @@ class Server { } /** + * @param callback * @private * @returns {void} */ @@ -2853,7 +2844,7 @@ class Server { * @returns {Promise} */ async logStatus() { - const { isColorSupported, cyan, red } = require("colorette"); + const { cyan, isColorSupported, red } = require("colorette"); /** * @param {Compiler["options"]} compilerOptions @@ -2939,7 +2930,7 @@ class Server { try { isIP = ipaddr.parse(this.options.host); - } catch (error) { + } catch { // Ignore } @@ -3085,7 +3076,7 @@ class Server { headers = headers( req, res, - // eslint-disable-next-line no-undefined + this.middleware ? this.middleware.context : undefined, ); } @@ -3096,7 +3087,6 @@ class Server { const allHeaders = []; if (!Array.isArray(headers)) { - // eslint-disable-next-line guard-for-in for (const name in headers) { // @ts-ignore allHeaders.push({ key: name, value: headers[name] }); @@ -3137,16 +3127,14 @@ class Server { // support "." as a subdomain wildcard // e.g. ".example.com" will allow "example.com", "www.example.com", "subdomain.example.com", etc - if (allowedHost.startsWith(".")) { - // "example.com" (value === allowedHost.substring(1)) + if ( + allowedHost.startsWith(".") && // "example.com" (value === allowedHost.substring(1)) // "*.example.com" (value.endsWith(allowedHost)) - if ( - value === allowedHost.substring(1) || + (value === allowedHost.slice(1) || /** @type {string} */ - (value).endsWith(allowedHost) - ) { - return true; - } + (value).endsWith(allowedHost)) + ) { + return true; } } } @@ -3194,12 +3182,12 @@ class Server { } // use the node url-parser to retrieve the hostname from the host-header. - const hostname = url.parse( + const { hostname } = url.parse( // if header doesn't have scheme, add // for parsing. /^(.+:)?\/\//.test(header) ? header : `//${header}`, false, true, - ).hostname; + ); if (hostname === null) { return false; @@ -3293,7 +3281,7 @@ class Server { * @param {any} [data] * @param {any} [params] */ - // eslint-disable-next-line class-methods-use-this + sendMessage(clients, type, data, params) { for (const client of clients) { // `sockjs` uses `1` to indicate client is ready to accept data @@ -3368,6 +3356,7 @@ class Server { */ watchFiles(watchPath, watchOptions) { const chokidar = require("chokidar"); + const watcher = chokidar.watch(watchPath, watchOptions); // disabling refreshing on changing the content @@ -3404,7 +3393,8 @@ class Server { if (this.options.ipc) { await /** @type {Promise} */ ( new Promise((resolve, reject) => { - const net = require("net"); + const net = require("node:net"); + const socket = new net.Socket(); socket.on( @@ -3544,7 +3534,6 @@ class Server { new Promise((resolve) => { /** @type {S} */ (this.server).close(() => { - // eslint-disable-next-line no-undefined this.server = undefined; resolve(); }); @@ -3560,7 +3549,7 @@ class Server { if (this.middleware) { await /** @type {Promise} */ ( new Promise((resolve, reject) => { - /** @type {import("webpack-dev-middleware").API}*/ + /** @type {import("webpack-dev-middleware").API} */ (this.middleware).close((error) => { if (error) { reject(error); @@ -3572,7 +3561,6 @@ class Server { }) ); - // eslint-disable-next-line no-undefined this.middleware = undefined; } } diff --git a/lib/getPort.js b/lib/getPort.js index 11cfb9dfe0..8be8874a54 100644 --- a/lib/getPort.js +++ b/lib/getPort.js @@ -6,21 +6,21 @@ * The code structure is similar to get-port, but it searches * ports deterministically like portfinder */ -const net = require("net"); -const os = require("os"); +const net = require("node:net"); +const os = require("node:os"); const minPort = 1024; const maxPort = 65_535; /** - * @return {Set} + * @returns {Set} */ const getLocalHosts = () => { const interfaces = os.networkInterfaces(); // Add undefined value for createServer function to use default host, // and default IPv4 host in case createServer defaults to IPv6. - // eslint-disable-next-line no-undefined + const results = new Set([undefined, "0.0.0.0"]); for (const _interface of Object.values(interfaces)) { @@ -37,7 +37,7 @@ const getLocalHosts = () => { /** * @param {number} basePort * @param {string | undefined} host - * @return {Promise} + * @returns {Promise} */ const checkAvailablePort = (basePort, host) => new Promise((resolve, reject) => { @@ -59,7 +59,7 @@ const checkAvailablePort = (basePort, host) => /** * @param {number} port * @param {Set} hosts - * @return {Promise} + * @returns {Promise} */ const getAvailablePort = async (port, hosts) => { /** @@ -70,7 +70,7 @@ const getAvailablePort = async (port, hosts) => { /* Check if the post is available on every local host name */ for (const host of hosts) { try { - await checkAvailablePort(port, host); // eslint-disable-line no-await-in-loop + await checkAvailablePort(port, host); } catch (error) { /* We throw an error only if the interface exists */ if ( @@ -89,7 +89,7 @@ const getAvailablePort = async (port, hosts) => { /** * @param {number} basePort * @param {string=} host - * @return {Promise} + * @returns {Promise} */ async function getPorts(basePort, host) { if (basePort < minPort || basePort > maxPort) { @@ -112,7 +112,7 @@ async function getPorts(basePort, host) { const portUnavailableErrors = new Set(["EADDRINUSE", "EACCES"]); while (port <= maxPort) { try { - const availablePort = await getAvailablePort(port, hosts); // eslint-disable-line no-await-in-loop + const availablePort = await getAvailablePort(port, hosts); return availablePort; } catch (error) { /* Try next port if port is busy; throw for any other error */ diff --git a/lib/servers/SockJSServer.js b/lib/servers/SockJSServer.js index 665146cd9b..fc2523ff85 100644 --- a/lib/servers/SockJSServer.js +++ b/lib/servers/SockJSServer.js @@ -12,7 +12,8 @@ const BaseServer = require("./BaseServer"); { // @ts-ignore const SockjsSession = require("sockjs/lib/transport").Session; - const decorateConnection = SockjsSession.prototype.decorateConnection; + + const { decorateConnection } = SockjsSession.prototype; /** * @param {import("http").IncomingMessage} req @@ -21,7 +22,7 @@ const BaseServer = require("./BaseServer"); SockjsSession.prototype.decorateConnection = function (req) { decorateConnection.call(this, req); - const connection = this.connection; + const { connection } = this; if ( connection.headers && diff --git a/lib/servers/WebsocketServer.js b/lib/servers/WebsocketServer.js index 283d1e2ccd..6612f5a06f 100644 --- a/lib/servers/WebsocketServer.js +++ b/lib/servers/WebsocketServer.js @@ -61,21 +61,16 @@ module.exports = class WebsocketServer extends BaseServer { ); const interval = setInterval(() => { - this.clients.forEach( - /** - * @param {ClientConnection} client - */ - (client) => { - if (client.isAlive === false) { - client.terminate(); - - return; - } - - client.isAlive = false; - client.ping(() => {}); - }, - ); + for (const client of this.clients) { + if (client.isAlive === false) { + client.terminate(); + + continue; + } + + client.isAlive = false; + client.ping(() => {}); + } }, WebsocketServer.heartbeatInterval); this.implementation.on( diff --git a/migration-v4.md b/migration-v4.md index 84543d9e79..9c1734fc27 100644 --- a/migration-v4.md +++ b/migration-v4.md @@ -44,8 +44,8 @@ v3: ```js module.exports = { devServer: { - before: function (app, server, compiler) { - app.get("/some/path", function (req, res) { + before (app, server, compiler) { + app.get("/some/path", (req, res) => { res.json({ custom: "response" }); }); }, @@ -58,8 +58,8 @@ v4: ```js module.exports = { devServer: { - onBeforeSetupMiddleware: function (devServer) { - devServer.app.get("/some/path", function (req, res) { + onBeforeSetupMiddleware (devServer) { + devServer.app.get("/some/path", (req, res) => { res.json({ custom: "response" }); }); }, @@ -74,8 +74,8 @@ v3: ```js module.exports = { devServer: { - after: function (app, server, compiler) { - app.get("/some/path", function (req, res) { + after (app, server, compiler) { + app.get("/some/path", (req, res) => { res.json({ custom: "response" }); }); }, @@ -88,8 +88,8 @@ v4: ```js module.exports = { devServer: { - onAfterSetupMiddleware: function (devServer) { - devServer.app.get("/some/path", function (req, res) { + onAfterSetupMiddleware (devServer) { + devServer.app.get("/some/path", (req, res) => { res.json({ custom: "response" }); }); }, @@ -328,7 +328,7 @@ Provide an array of objects in case you have multiple static folders: ```js module.exports = { - //... + // ... devServer: { static: [ { @@ -418,7 +418,7 @@ module.exports = { module.exports = { devServer: { open: { - target: ["first.html", `http://localhost:8080/second.html`], + target: ["first.html", "http://localhost:8080/second.html"], app: { name: "google-chrome", arguments: ["--incognito", "--new-window"], diff --git a/migration-v5.md b/migration-v5.md index 50f2e1f2d4..e2830d5eac 100644 --- a/migration-v5.md +++ b/migration-v5.md @@ -31,7 +31,7 @@ This document serves as a migration guide for `webpack-dev-server@5.0.0`. ```js module.exports = { - //... + // ... devServer: { server: { type: "spdy", // or use 'https' @@ -54,7 +54,7 @@ This document serves as a migration guide for `webpack-dev-server@5.0.0`. ```js module.exports = { - //... + // ... devServer: { server: { type: "https", // or use 'https' @@ -70,7 +70,7 @@ This document serves as a migration guide for `webpack-dev-server@5.0.0`. ```js module.exports = { - //... + // ... devServer: { server: { type: "https", @@ -88,23 +88,23 @@ This document serves as a migration guide for `webpack-dev-server@5.0.0`. ```js module.exports = { - //... + // ... devServer: { - onAfterSetupMiddleware: function (devServer) { + onAfterSetupMiddleware (devServer) { if (!devServer) { throw new Error("webpack-dev-server is not defined"); } - - devServer.app.get("/some/after-path", function (req, res) { + + devServer.app.get("/some/after-path", (req, res) => { res.json({ custom: "response" }); }); }, - onBeforeSetupMiddleware: function (devServer) { + onBeforeSetupMiddleware (devServer) { if (!devServer) { throw new Error("webpack-dev-server is not defined"); } - - devServer.app.get("/some/before-path", function (req, res) { + + devServer.app.get("/some/before-path", (req, res) => { res.json({ custom: "response" }); }); }, @@ -165,7 +165,7 @@ v4: ```js module.exports = { - //... + // ... devServer: { proxy: { "/api": { @@ -181,7 +181,7 @@ v5: ```js module.exports = { - //... + // ... devServer: { proxy: [ { diff --git a/package-lock.json b/package-lock.json index 80988c6383..153ed5c5a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,12 +51,14 @@ "@babel/runtime": "^7.25.9", "@commitlint/cli": "^19.5.0", "@commitlint/config-conventional": "^19.5.0", + "@eslint/markdown": "^7.0.0", "@hono/node-server": "^1.13.3", "@types/compression": "^1.7.2", "@types/node": "^22.8.4", "@types/node-forge": "^1.3.1", "@types/sockjs-client": "^1.5.1", "@types/trusted-types": "^2.0.2", + "@typescript-eslint/eslint-plugin": "^8.36.0", "acorn": "^8.14.0", "babel-jest": "^29.5.0", "babel-loader": "^10.0.0", @@ -65,10 +67,13 @@ "core-js": "^3.38.1", "cspell": "^8.15.5", "css-loader": "^7.1.1", - "eslint": "^8.57.1", - "eslint-config-prettier": "^9.1.0", - "eslint-config-webpack": "^1.2.5", - "eslint-plugin-import": "^2.31.0", + "eslint": "^9.30.1", + "eslint-config-prettier": "^10.1.5", + "eslint-config-webpack": "^4.3.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jest": "^29.0.1", + "eslint-plugin-jsdoc": "^51.3.4", + "eslint-plugin-n": "^17.21.0", "execa": "^5.1.1", "hono": "^4.6.8", "html-webpack-plugin": "^5.6.3", @@ -95,6 +100,7 @@ "supertest": "^7.0.0", "tcp-port-used": "^1.0.2", "typescript": "^5.7.2", + "typescript-eslint": "^8.36.0", "wait-for-expect": "^3.0.2", "webpack": "^5.94.0", "webpack-cli": "^5.0.1", @@ -926,6 +932,16 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.27.1", "dev": true, @@ -1708,6 +1724,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { "version": "7.27.3", "dev": true, @@ -2419,6 +2445,23 @@ "node": ">=10.0.0" } }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.52.0.tgz", + "integrity": "sha512-BXuN7BII+8AyNtn57euU2Yxo9yA/KUDNzrpXyi3pfqKmBhhysR6ZWOebFh3vyPoqA3/j1SOvGgucElMGwlXing==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.8", + "@typescript-eslint/types": "^8.34.1", + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~4.1.0" + }, + "engines": { + "node": ">=20.11.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.7.0", "dev": true, @@ -2455,15 +2498,55 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", + "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -2471,7 +2554,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2479,6 +2562,8 @@ }, "node_modules/@eslint/eslintrc/node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", "dependencies": { @@ -2494,18 +2579,19 @@ }, "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, "license": "Python-2.0" }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2513,6 +2599,8 @@ }, "node_modules/@eslint/eslintrc/node_modules/js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "license": "MIT", "dependencies": { @@ -2524,26 +2612,82 @@ }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", + "node_modules/@eslint/js": { + "version": "9.30.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.30.1.tgz", + "integrity": "sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://eslint.org/donate" } }, - "node_modules/@eslint/js": { - "version": "8.57.1", + "node_modules/@eslint/markdown": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-7.0.0.tgz", + "integrity": "sha512-0WNH6pSFHNlWSlNaIFQP0sLHpMUJw1FaJtyqapvGqOt0ISRgTUkTLVT0hT/zekDA1QlP2TT8pwjPkqYTu2s8yg==", "dev": true, "license": "MIT", + "workspaces": [ + "examples/*" + ], + "dependencies": { + "@eslint/core": "^0.14.0", + "@eslint/plugin-kit": "^0.3.1", + "github-slugger": "^2.0.0", + "mdast-util-from-markdown": "^2.0.2", + "mdast-util-frontmatter": "^2.0.1", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-frontmatter": "^2.0.0", + "micromark-extension-gfm": "^3.0.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz", + "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@hono/node-server": { @@ -2559,17 +2703,42 @@ "hono": "^4" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/module-importer": { @@ -2584,10 +2753,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", @@ -3451,6 +3629,8 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", "dependencies": { @@ -3463,6 +3643,8 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", "engines": { @@ -3471,6 +3653,8 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", "dependencies": { @@ -3498,6 +3682,20 @@ "node": ">=14" } }, + "node_modules/@pkgr/core": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", + "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, "node_modules/@puppeteer/browsers": { "version": "2.10.5", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.5.tgz", @@ -3559,6 +3757,67 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@stylistic/eslint-plugin": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.1.0.tgz", + "integrity": "sha512-TJRJul4u/lmry5N/kyCU+7RWWOk0wyXN+BncRlDYBqpLFnzXkd7QGVfN7KewarFIXv0IX0jSF/Ksu7aHWEDeuw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/types": "^8.34.1", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "estraverse": "^5.3.0", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0" + } + }, + "node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@stylistic/eslint-plugin/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@stylistic/eslint-plugin/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "dev": true, @@ -3660,6 +3919,16 @@ "@types/node": "*" } }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/eslint": { "version": "9.6.1", "devOptional": true, @@ -3679,7 +3948,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.7", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "devOptional": true, "license": "MIT" }, @@ -3769,6 +4040,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.5", "license": "MIT" @@ -3778,6 +4059,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.15.32", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.32.tgz", @@ -3864,6 +4152,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.18.1", "license": "MIT", @@ -3895,71 +4190,349 @@ "@types/node": "*" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.36.0.tgz", + "integrity": "sha512-lZNihHUVB6ZZiPBNgOQGSxUASI7UJWhT8nHyUGCnaQ28XFCw98IfrMCG3rUl1uwUWoAvodJQby2KTs79UTcrAg==", "dev": true, - "license": "ISC" - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "devOptional": true, "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.36.0", + "@typescript-eslint/type-utils": "8.36.0", + "@typescript-eslint/utils": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.36.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "devOptional": true, - "license": "MIT" + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "devOptional": true, + "node_modules/@typescript-eslint/parser": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.36.0.tgz", + "integrity": "sha512-FuYgkHwZLuPbZjQHzJXrtXreJdFMKl16BFYyRrLxDhWr6Qr7Kbcu2s1Yhu8tsiMXw1S0W1pjfFfYEt+R604s+Q==", + "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" + "@typescript-eslint/scope-manager": "8.36.0", + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/typescript-estree": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "devOptional": true, + "node_modules/@typescript-eslint/project-service": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.36.0.tgz", + "integrity": "sha512-JAhQFIABkWccQYeLMrHadu/fhpzmSQ1F1KXkpzqiVxA/iYI6UnRt2trqXHt1sYEcw1mxLnB9rKMsOxXPxowN/g==", + "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" + "@typescript-eslint/tsconfig-utils": "^8.36.0", + "@typescript-eslint/types": "^8.36.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "devOptional": true, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.36.0.tgz", + "integrity": "sha512-wCnapIKnDkN62fYtTGv2+RY8FlnBYA3tNm0fm91kc2BjPhV2vIjwwozJ7LToaLAyb1ca8BxrS7vT+Pvvf7RvqA==", + "dev": true, "license": "MIT", "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.36.0.tgz", + "integrity": "sha512-Nhh3TIEgN18mNbdXpd5Q8mSCBnrZQeY9V7Ca3dqYvNDStNIGRmJA6dmrIPMJ0kow3C7gcQbpsG2rPzy1Ks/AnA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.36.0.tgz", + "integrity": "sha512-5aaGYG8cVDd6cxfk/ynpYzxBRZJk7w/ymto6uiyUFtdCozQIsQWh7M28/6r57Fwkbweng8qAzoMCPwSJfWlmsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.36.0", + "@typescript-eslint/utils": "8.36.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.36.0.tgz", + "integrity": "sha512-xGms6l5cTJKQPZOKM75Dl9yBfNdGeLRsIyufewnxT4vZTrjC0ImQT4fj8QmtJK84F58uSh5HVBSANwcfiXxABQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.36.0.tgz", + "integrity": "sha512-JaS8bDVrfVJX4av0jLpe4ye0BpAaUW7+tnS4Y4ETa3q7NoZgzYbN9zDQTJ8kPb5fQ4n0hliAt9tA4Pfs2zA2Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.36.0", + "@typescript-eslint/tsconfig-utils": "8.36.0", + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.36.0.tgz", + "integrity": "sha512-VOqmHu42aEMT+P2qYjylw6zP/3E/HvptRwdn/PZxyV27KhZg2IOszXod4NcXisWzPAGSS4trE/g4moNj6XmH2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.36.0", + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/typescript-estree": "8.36.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.36.0.tgz", + "integrity": "sha512-vZrhV2lRPWDuGoxcmrzRZyxAggPL+qp3WzUrlZD+slFueDiYHxeBa34dUXPuC0RmGKzl4lS5kFJYvKCq9cnNDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.36.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", "devOptional": true, "license": "Apache-2.0", "dependencies": { @@ -4140,6 +4713,8 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4266,6 +4841,16 @@ "node": ">= 8" } }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/argparse": { "version": "1.0.10", "dev": true, @@ -4979,6 +5564,20 @@ "devOptional": true, "license": "MIT" }, + "node_modules/builtin-modules": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-5.0.0.tgz", + "integrity": "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bundle-name": { "version": "4.1.0", "license": "MIT", @@ -5101,6 +5700,17 @@ ], "license": "CC-BY-4.0" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chalk": { "version": "5.4.1", "dev": true, @@ -5134,6 +5744,17 @@ "node": ">=10" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chokidar": { "version": "3.6.0", "license": "MIT", @@ -5208,6 +5829,31 @@ "node": ">= 10.0" } }, + "node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/clean-regexp/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/clear-module": { "version": "4.1.2", "dev": true, @@ -5415,6 +6061,16 @@ "node": ">= 6" } }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/compare-func": { "version": "2.0.0", "dev": true, @@ -7283,6 +7939,20 @@ "dev": true, "license": "MIT" }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/dedent": { "version": "1.6.0", "dev": true, @@ -7405,6 +8075,16 @@ "node": ">= 0.8" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/destroy": { "version": "1.2.0", "license": "MIT", @@ -7433,6 +8113,20 @@ "version": "2.1.0", "license": "MIT" }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/devtools-protocol": { "version": "0.0.1452169", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1452169.tgz", @@ -7467,21 +8161,10 @@ "node": ">=6" } }, - "node_modules/doctrine": { - "version": "3.0.0", + "node_modules/dom-converter": { + "version": "0.2.0", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "dev": true, - "license": "MIT", + "license": "MIT", "dependencies": { "utila": "~0.4" } @@ -7965,79 +8648,185 @@ } }, "node_modules/eslint": { - "version": "8.57.1", + "version": "9.30.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.30.1.tgz", + "integrity": "sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.14.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.30.1", + "@eslint/plugin-kit": "^0.3.1", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-compat-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", + "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-compat-utils/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", + "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", "dev": true, "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, "peerDependencies": { "eslint": ">=7.0.0" } }, "node_modules/eslint-config-webpack": { - "version": "1.2.5", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-webpack/-/eslint-config-webpack-4.3.0.tgz", + "integrity": "sha512-G2mePdT5zOOPS+lYtNKAdLqIgSSRCswirgrWh1+Lk1R2UY2r7q5XTtJbTguOR3ukfFySpYx0vHPTdN8TxpFQtw==", "dev": true, "license": "MIT", + "dependencies": { + "detect-indent": "^7.0.1", + "jsonc-eslint-parser": "^2.4.0", + "semver": "^7.7.2", + "sort-package-json": "^3.3.1" + }, "engines": { - "node": ">= 4" + "node": ">= 18.20.0" }, "peerDependencies": { - "eslint": "^3.13.0 || >=4.0.0" + "@eslint/js": ">= 9.28.0", + "@eslint/markdown": ">= 6.5.0", + "@stylistic/eslint-plugin": ">= 4.4.1", + "eslint": ">= 9.28.0", + "eslint-config-prettier": "^10.1.5", + "eslint-plugin-import": ">= 2.31.0", + "eslint-plugin-jest": ">= 28.12.0", + "eslint-plugin-jsdoc": ">= 50.7.1", + "eslint-plugin-n": ">= 17.19.0", + "eslint-plugin-prettier": ">= 5.4.1", + "eslint-plugin-unicorn": ">= 59.0.1", + "globals": ">= 16.2.0", + "prettier": ">= 3.5.3", + "typescript": ">= 5.0.0", + "typescript-eslint": ">= 8.34.0" + }, + "peerDependenciesMeta": { + "@eslint/markdown": { + "optional": true + }, + "eslint-plugin-jest": { + "optional": true + }, + "eslint-plugin-jsdoc": { + "optional": true + }, + "eslint-plugin-n": { + "optional": true + }, + "typescript": { + "optional": true + }, + "typescript-eslint": { + "optional": true + } + } + }, + "node_modules/eslint-config-webpack/node_modules/detect-indent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", + "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/eslint-config-webpack/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/eslint-import-resolver-node": { @@ -8059,7 +8848,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.12.0", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "license": "MIT", "dependencies": { @@ -8076,35 +8867,61 @@ }, "node_modules/eslint-module-utils/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, + "node_modules/eslint-plugin-es-x": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz", + "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/ota-meshi", + "https://opencollective.com/eslint" + ], + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.11.0", + "eslint-compat-utils": "^0.5.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": ">=8" + } + }, "node_modules/eslint-plugin-import": { - "version": "2.31.0", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", "dependencies": { "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", + "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", - "is-core-module": "^2.15.1", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", + "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "engines": { @@ -8133,402 +8950,673 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "devOptional": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", + "node_modules/eslint-plugin-jest": { + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.0.1.tgz", + "integrity": "sha512-EE44T0OSMCeXhDrrdsbKAhprobKkPtJTbQz5yEktysNpHeDZTAL1SfDTNKmcFfJkY6yrQLtTKZALrD3j/Gpmiw==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@typescript-eslint/utils": "^8.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": "^20.12.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/eslint-plugin-jsdoc": { + "version": "51.3.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-51.3.4.tgz", + "integrity": "sha512-maz6qa95+sAjMr9m5oRyfejc+mnyQWsWSe9oyv9371bh4/T0kWOMryJNO4h8rEd97wo/9lbzwi3OOX4rDhnAzg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "color-convert": "^2.0.1" + "@es-joy/jsdoccomment": "~0.52.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.4.1", + "escape-string-regexp": "^4.0.0", + "espree": "^10.4.0", + "esquery": "^1.6.0", + "parse-imports-exports": "^0.2.4", + "semver": "^7.7.2", + "spdx-expression-parse": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=20.11.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", + "node_modules/eslint-plugin-jsdoc/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", + "node_modules/eslint-plugin-jsdoc/node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", + "node_modules/eslint-plugin-n": { + "version": "17.21.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.21.0.tgz", + "integrity": "sha512-1+iZ8We4ZlwVMtb/DcHG3y5/bZOdazIpa/4TySo22MLKdwrLcfrX0hbadnCvykSQCCmkAnWmIP8jZVb2AAq29A==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "@eslint-community/eslint-utils": "^4.5.0", + "enhanced-resolve": "^5.17.1", + "eslint-plugin-es-x": "^7.8.0", + "get-tsconfig": "^4.8.1", + "globals": "^15.11.0", + "ignore": "^5.3.2", + "minimatch": "^9.0.5", + "semver": "^7.6.3", + "ts-declaration-location": "^1.0.6" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" + "peerDependencies": { + "eslint": ">=8.23.0" } }, - "node_modules/eslint/node_modules/file-entry-cache": { - "version": "6.0.1", + "node_modules/eslint-plugin-n/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", + "node_modules/eslint-plugin-n/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/flat-cache": { - "version": "3.2.0", + "node_modules/eslint-plugin-n/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", + "node_modules/eslint-plugin-n/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=10.13.0" + "node": ">=10" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", + "node_modules/eslint-plugin-prettier": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.1.tgz", + "integrity": "sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "type-fest": "^0.20.2" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.7" }, "engines": { - "node": ">=8" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" + "url": "https://opencollective.com/eslint-plugin-prettier" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" + "node_modules/eslint-plugin-unicorn": { + "version": "59.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-59.0.1.tgz", + "integrity": "sha512-EtNXYuWPUmkgSU2E7Ttn57LbRREQesIP1BiLn7OZLKodopKfDXfBUkC/0j6mpw2JExwf43Uf3qLSvrSvppgy8Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "@eslint-community/eslint-utils": "^4.5.1", + "@eslint/plugin-kit": "^0.2.7", + "ci-info": "^4.2.0", + "clean-regexp": "^1.0.0", + "core-js-compat": "^3.41.0", + "esquery": "^1.6.0", + "find-up-simple": "^1.0.1", + "globals": "^16.0.0", + "indent-string": "^5.0.0", + "is-builtin-module": "^5.0.0", + "jsesc": "^3.1.0", + "pluralize": "^8.0.0", + "regexp-tree": "^0.1.27", + "regjsparser": "^0.12.0", + "semver": "^7.7.1", + "strip-indent": "^4.0.0" }, "engines": { - "node": ">=10" + "node": "^18.20.0 || ^20.10.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=9.22.0" } }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", + "node_modules/eslint-plugin-unicorn/node_modules/@eslint/core": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "peer": true, "dependencies": { - "p-limit": "^3.0.2" + "@types/json-schema": "^7.0.15" }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/@eslint/plugin-kit": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", + "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@eslint/core": "^0.13.0", + "levn": "^0.4.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/eslint/node_modules/path-exists": { - "version": "4.0.0", + "node_modules/eslint-plugin-unicorn/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", + "peer": true, "engines": { "node": ">=8" } }, - "node_modules/eslint/node_modules/rimraf": { - "version": "3.0.2", + "node_modules/eslint-plugin-unicorn/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", + "node_modules/eslint-plugin-unicorn/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { "node": ">=10" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/espree": { - "version": "9.6.1", - "dev": true, + "node_modules/eslint-scope": { + "version": "5.1.1", + "devOptional": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8.0.0" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.4.3", + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://opencollective.com/eslint" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/esprima": { - "version": "4.0.1", + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/esquery": { - "version": "1.6.0", + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=4.0" + "node": ">=7.0.0" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "devOptional": true, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { + "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": ">=4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "devOptional": true, - "license": "BSD-2-Clause", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "devOptional": true, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, - "node_modules/esutils": { - "version": "2.0.3", + "node_modules/eslint/node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=16.0.0" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", "dev": true, "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "license": "MIT" - }, - "node_modules/events": { - "version": "3.3.0", - "devOptional": true, + "node_modules/eslint/node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, "engines": { - "node": ">=0.8.x" + "node": ">=16" } }, - "node_modules/eventsource": { - "version": "2.0.2", + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, "engines": { - "node": ">=12.0.0" + "node": ">=10.13.0" } }, - "node_modules/execa": { - "version": "5.1.1", + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/eventsource": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", @@ -8677,6 +9765,14 @@ "version": "3.1.3", "license": "MIT" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0", + "peer": true + }, "node_modules/fast-equals": { "version": "5.2.2", "dev": true, @@ -8692,6 +9788,23 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "dev": true, @@ -8731,12 +9844,28 @@ }, "node_modules/fastq": { "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/faye-websocket": { "version": "0.11.4", "license": "Apache-2.0", @@ -8881,6 +10010,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat": { "version": "5.0.2", "dev": true, @@ -8978,6 +10121,15 @@ "node": ">= 6" } }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/formidable": { "version": "3.5.4", "dev": true, @@ -9347,6 +10499,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/get-uri": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", @@ -9362,6 +10527,16 @@ "node": ">= 14" } }, + "node_modules/git-hooks-list": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-4.1.1.tgz", + "integrity": "sha512-cmP497iLq54AZnv4YRAEMnEyQ1eIn4tGKbmswqwmFV4GBnAqE8NLtWxxdXa++AalfgL5EBH4IxTPyquEuGY/jA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/fisker/git-hooks-list?sponsor=1" + } + }, "node_modules/git-raw-commits": { "version": "4.0.0", "dev": true, @@ -9647,6 +10822,13 @@ "dev": true, "license": "ISC" }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "dev": true, + "license": "ISC" + }, "node_modules/glob": { "version": "7.2.3", "dev": true, @@ -9696,11 +10878,17 @@ } }, "node_modules/globals": { - "version": "11.12.0", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globalthis": { @@ -9734,6 +10922,8 @@ }, "node_modules/graphemer": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, "license": "MIT" }, @@ -10169,6 +11359,8 @@ }, "node_modules/ignore": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { @@ -10487,6 +11679,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-builtin-module": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-5.0.0.tgz", + "integrity": "sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "builtin-modules": "^5.0.0" + }, + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-callable": { "version": "1.2.7", "dev": true, @@ -10701,14 +11910,6 @@ "node": ">=8" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-obj": { "version": "3.0.0", "license": "MIT", @@ -12304,6 +13505,16 @@ "dev": true, "license": "MIT" }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz", + "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/jsdom": { "version": "20.0.3", "dev": true, @@ -12399,15 +13610,78 @@ "node": ">=6" } }, - "node_modules/jsonparse": { - "version": "1.3.1", + "node_modules/jsonc-eslint-parser": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", + "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/JSONStream": { + "license": "MIT", + "dependencies": { + "acorn": "^8.5.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/JSONStream": { "version": "1.3.5", "dev": true, "license": "(MIT OR Apache-2.0)", @@ -12948,6 +14222,17 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/lower-case": { "version": "2.0.2", "dev": true, @@ -13003,6 +14288,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/marked": { "version": "12.0.2", "dev": true, @@ -13021,6 +14317,251 @@ "node": ">= 0.4" } }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", + "integrity": "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "escape-string-regexp": "^5.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/media-typer": { "version": "0.3.0", "license": "MIT", @@ -13048,39 +14589,657 @@ "node_modules/memorystream": { "version": "0.3.1", "dev": true, - "engines": { - "node": ">= 0.10.0" + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/meow": { + "version": "12.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "devOptional": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-frontmatter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", + "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" } }, - "node_modules/meow": { - "version": "12.1.1", + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "engines": { - "node": ">=16.10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/merge-descriptors": { - "version": "1.0.3", + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "devOptional": true, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT" }, - "node_modules/methods": { - "version": "1.1.2", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, "node_modules/micromatch": { "version": "4.0.8", @@ -13876,6 +16035,16 @@ "node": ">=8" } }, + "node_modules/parse-imports-exports": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz", + "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-statements": "1.0.11" + } + }, "node_modules/parse-json": { "version": "5.2.0", "dev": true, @@ -13901,6 +16070,13 @@ "node": ">= 0.10" } }, + "node_modules/parse-statements": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz", + "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==", + "dev": true, + "license": "MIT" + }, "node_modules/parse5": { "version": "7.3.0", "dev": true, @@ -14048,6 +16224,17 @@ "node": ">= 6" } }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "dev": true, @@ -14177,6 +16364,20 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-error": { "version": "4.0.0", "dev": true, @@ -14457,6 +16658,8 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -14686,6 +16889,17 @@ "node": ">=4" } }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "dev": true, @@ -14833,6 +17047,16 @@ "node": ">=8" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/resolve.exports": { "version": "2.0.3", "dev": true, @@ -14890,6 +17114,8 @@ }, "node_modules/reusify": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { @@ -14969,6 +17195,8 @@ }, "node_modules/run-parallel": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -15521,6 +17749,84 @@ "node": ">= 14" } }, + "node_modules/sort-object-keys": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sort-package-json": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.4.0.tgz", + "integrity": "sha512-97oFRRMM2/Js4oEA9LJhjyMlde+2ewpZQf53pgue27UkbEXfHJnDzHlUxQ/DWUkzqmp7DFwJp8D+wi/TYeQhpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-indent": "^7.0.1", + "detect-newline": "^4.0.1", + "git-hooks-list": "^4.0.0", + "is-plain-obj": "^4.1.0", + "semver": "^7.7.1", + "sort-object-keys": "^1.1.3", + "tinyglobby": "^0.2.12" + }, + "bin": { + "sort-package-json": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/sort-package-json/node_modules/detect-indent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", + "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/sort-package-json/node_modules/detect-newline": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", + "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sort-package-json/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sort-package-json/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/source-map": { "version": "0.6.1", "devOptional": true, @@ -16264,6 +18570,23 @@ "dev": true, "license": "MIT" }, + "node_modules/synckit": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz", + "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@pkgr/core": "^0.2.4" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, "node_modules/tapable": { "version": "2.2.2", "devOptional": true, @@ -16454,11 +18777,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, "node_modules/thingies": { "version": "1.21.0", "license": "Unlicense", @@ -16612,6 +18930,55 @@ "node": ">=8" } }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-declaration-location": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ts-declaration-location/-/ts-declaration-location-1.0.7.tgz", + "integrity": "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==", + "dev": true, + "funding": [ + { + "type": "ko-fi", + "url": "https://ko-fi.com/rebeccastevens" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/ts-declaration-location" + } + ], + "license": "BSD-3-Clause", + "dependencies": { + "picomatch": "^4.0.2" + }, + "peerDependencies": { + "typescript": ">=4.0.0" + } + }, + "node_modules/ts-declaration-location/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "dev": true, @@ -16781,6 +19148,29 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.36.0.tgz", + "integrity": "sha512-fTCqxthY+h9QbEgSIBfL9iV6CvKDFuoxg6bHPNpJ9HIUzS+jy2lCEyCmGyZRWEBSaykqcDPf1SJ+BfCI8DRopA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.36.0", + "@typescript-eslint/parser": "8.36.0", + "@typescript-eslint/utils": "8.36.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/uglify-js": { "version": "3.19.3", "dev": true, @@ -16861,6 +19251,65 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/universalify": { "version": "0.2.0", "dev": true, @@ -17667,6 +20116,17 @@ "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/package.json b/package.json index 44db95e4c7..b804259073 100644 --- a/package.json +++ b/package.json @@ -2,27 +2,24 @@ "name": "webpack-dev-server", "version": "5.2.2", "description": "Serves a webpack app. Updates the browser on changes.", - "bin": "bin/webpack-dev-server.js", - "main": "lib/Server.js", - "types": "types/lib/Server.d.ts", - "author": "Tobias Koppers @sokra", - "bugs": "https://github.com/webpack/webpack-dev-server/issues", "homepage": "https://github.com/webpack/webpack-dev-server#readme", + "bugs": "https://github.com/webpack/webpack-dev-server/issues", "repository": "https://github.com/webpack/webpack-dev-server", - "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, + "license": "MIT", + "author": "Tobias Koppers @sokra", + "main": "lib/Server.js", + "types": "types/lib/Server.d.ts", + "bin": "bin/webpack-dev-server.js", "files": [ "bin", "lib", "client", "types" ], - "engines": { - "node": ">= 18.12.0" - }, "scripts": { "fmt:check": "prettier \"{**/*,*}.{js,json,md,yml,css,ts}\" --list-different", "lint:prettier": "prettier --cache --list-different .", @@ -85,6 +82,7 @@ "@babel/runtime": "^7.25.9", "@commitlint/cli": "^19.5.0", "@commitlint/config-conventional": "^19.5.0", + "@eslint/markdown": "^7.0.0", "@hono/node-server": "^1.13.3", "@types/compression": "^1.7.2", "@types/node": "^22.8.4", @@ -99,10 +97,13 @@ "core-js": "^3.38.1", "cspell": "^8.15.5", "css-loader": "^7.1.1", - "eslint": "^8.57.1", - "eslint-config-prettier": "^9.1.0", - "eslint-config-webpack": "^1.2.5", - "eslint-plugin-import": "^2.31.0", + "eslint": "^9.30.1", + "eslint-config-prettier": "^10.1.5", + "eslint-config-webpack": "^4.3.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jest": "^29.0.1", + "eslint-plugin-jsdoc": "^51.3.4", + "eslint-plugin-n": "^17.21.0", "execa": "^5.1.1", "hono": "^4.6.8", "html-webpack-plugin": "^5.6.3", @@ -129,6 +130,7 @@ "supertest": "^7.0.0", "tcp-port-used": "^1.0.2", "typescript": "^5.7.2", + "typescript-eslint": "^8.36.0", "wait-for-expect": "^3.0.2", "webpack": "^5.94.0", "webpack-cli": "^5.0.1", @@ -144,5 +146,8 @@ "webpack": { "optional": true } + }, + "engines": { + "node": ">= 18.12.0" } } diff --git a/scripts/extend-webpack-types.js b/scripts/extend-webpack-types.js index f46931e65a..c4f3274149 100644 --- a/scripts/extend-webpack-types.js +++ b/scripts/extend-webpack-types.js @@ -1,11 +1,14 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const fs = require("graceful-fs"); +/** + * + */ async function extendTypes() { const typesPath = path.resolve(__dirname, "../types/lib/Server.d.ts"); - const content = await fs.promises.readFile(typesPath, "utf-8"); + const content = await fs.promises.readFile(typesPath, "utf8"); const newContent = `${content} // DO NOT REMOVE THIS! type DevServerConfiguration = Configuration; diff --git a/scripts/globalSetupTest.js b/scripts/globalSetupTest.js index cfdc90ef8b..0b7195d872 100644 --- a/scripts/globalSetupTest.js +++ b/scripts/globalSetupTest.js @@ -1,6 +1,5 @@ "use strict"; -// eslint-disable-next-line import/no-extraneous-dependencies const tcpPortUsed = require("tcp-port-used"); const { version } = require("webpack"); const ports = require("../test/ports-map"); @@ -8,14 +7,17 @@ const ports = require("../test/ports-map"); // eslint-disable-next-line no-console console.log(`\n Running tests for webpack @${version} \n`); +/** + * + */ async function validatePorts() { const samples = []; - Object.keys(ports).forEach((key) => { + for (const key of Object.keys(ports)) { const value = ports[key]; const arr = Array.isArray(value) ? value : [value]; - arr.forEach((port) => { + for (const port of arr) { const check = tcpPortUsed.check(port, "localhost").then((inUse) => { if (inUse) { throw new Error(`${port} has already used. [${key}]`); @@ -23,14 +25,14 @@ async function validatePorts() { }); samples.push(check); - }); - }); + } + } try { await Promise.all(samples); - } catch (e) { + } catch (err) { // eslint-disable-next-line no-console - console.error(e); + console.error(err); process.exit(1); } } diff --git a/scripts/prepare-test-for-old-node.js b/scripts/prepare-test-for-old-node.js index 5499e96996..b3b5d18f7b 100644 --- a/scripts/prepare-test-for-old-node.js +++ b/scripts/prepare-test-for-old-node.js @@ -1,13 +1,16 @@ "use strict"; -const path = require("path"); -const fs = require("fs"); +const fs = require("node:fs"); +const path = require("node:path"); +/** + * + */ async function setup() { const serverCodePath = path.resolve(__dirname, "../lib/Server.js"); - let serverCode = await fs.promises.readFile(serverCodePath, "utf-8"); + let serverCode = await fs.promises.readFile(serverCodePath, "utf8"); - serverCode = serverCode.replace( + serverCode = serverCode.replaceAll( /\(await import\((".+")\)\)\.default/g, "require($1)", ); diff --git a/test/cli/allowedHosts-option.test.js b/test/cli/allowedHosts-option.test.js index 47a4005d9a..548314d148 100644 --- a/test/cli/allowedHosts-option.test.js +++ b/test/cli/allowedHosts-option.test.js @@ -12,7 +12,7 @@ describe('"allowedHosts" CLI option', () => { "auto", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--allowed-hosts all"', async () => { @@ -23,7 +23,7 @@ describe('"allowedHosts" CLI option', () => { "all", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--allowed-hosts testhouse.com"', async () => { @@ -34,7 +34,7 @@ describe('"allowedHosts" CLI option', () => { "testhouse.com", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--allowed-hosts testhost.com --allowed-hosts testhost1.com"', async () => { @@ -47,6 +47,6 @@ describe('"allowedHosts" CLI option', () => { "testhost1.com", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); }); diff --git a/test/cli/basic.test.js b/test/cli/basic.test.js index 98a5e33c79..3601ad23a2 100644 --- a/test/cli/basic.test.js +++ b/test/cli/basic.test.js @@ -1,9 +1,9 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const execa = require("execa"); const stripAnsi = require("strip-ansi-v6"); -const { testBin, normalizeStderr } = require("../helpers/test-bin"); +const { normalizeStderr, testBin } = require("../helpers/test-bin"); const port = require("../ports-map")["cli-basic"]; const isMacOS = process.platform === "darwin"; @@ -13,7 +13,7 @@ describe("basic", () => { (isMacOS ? it.skip : it)("should generate correct cli flags", async () => { const { exitCode, stdout } = await testBin(["--help"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stripAnsi(stdout)).toMatchSnapshot(); }); }); @@ -26,7 +26,7 @@ describe("basic", () => { port, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -38,7 +38,7 @@ describe("basic", () => { "localhost", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); @@ -53,7 +53,7 @@ describe("basic", () => { port, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -68,7 +68,7 @@ describe("basic", () => { port, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -207,7 +207,7 @@ describe("basic", () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stdout).toContain("client/index.js?"); }); @@ -226,7 +226,7 @@ describe("basic", () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stdout).toContain("client/index.js?"); expect(stdout).toContain("foo.js"); }); @@ -244,7 +244,7 @@ describe("basic", () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stdout).toContain("client/index.js?"); }); @@ -263,7 +263,7 @@ describe("basic", () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stdout).toContain("foo.js"); }); @@ -275,7 +275,7 @@ describe("basic", () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stdout).toContain("client/index.js?"); expect(stdout).toContain("foo.js"); }); @@ -288,7 +288,7 @@ describe("basic", () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stdout).not.toContain("client/index.js?"); expect(stdout).toContain("foo.js"); }); @@ -301,7 +301,7 @@ describe("basic", () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stdout).toContain("webpack/hot/dev-server"); }); @@ -318,7 +318,7 @@ describe("basic", () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stdout).toContain("client/index.js"); }); diff --git a/test/cli/bonjour-option.test.js b/test/cli/bonjour-option.test.js index 14fb7a1799..77d1df223b 100644 --- a/test/cli/bonjour-option.test.js +++ b/test/cli/bonjour-option.test.js @@ -1,8 +1,8 @@ "use strict"; -const fs = require("fs"); +const fs = require("node:fs"); const Server = require("../../lib/Server"); -const { testBin, normalizeStderr } = require("../helpers/test-bin"); +const { normalizeStderr, testBin } = require("../helpers/test-bin"); const port = require("../ports-map")["cli-bonjour"]; const defaultCertificateDir = Server.findCacheDir(); @@ -17,7 +17,7 @@ describe('"bonjour" CLI option', () => { outputKillStr: /Broadcasting/, }); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot(); }); @@ -29,7 +29,7 @@ describe('"bonjour" CLI option', () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect( normalizeStderr(stderr, { ipv6: true, https: true }), ).toMatchSnapshot(); @@ -42,7 +42,7 @@ describe('"bonjour" CLI option', () => { "--no-bonjour", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot(); }); }); diff --git a/test/cli/client-option.test.js b/test/cli/client-option.test.js index 61a4eb5432..d9c95c609f 100644 --- a/test/cli/client-option.test.js +++ b/test/cli/client-option.test.js @@ -12,7 +12,7 @@ describe('"client" CLI option', () => { "sockjs", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-web-socket-transport ws"', async () => { @@ -23,19 +23,19 @@ describe('"client" CLI option', () => { "ws", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-overlay"', async () => { const { exitCode } = await testBin(["--port", port, "--client-overlay"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--no-client-overlay"', async () => { const { exitCode } = await testBin(["--port", port, "--no-client-overlay"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-overlay-errors"', async () => { @@ -45,7 +45,7 @@ describe('"client" CLI option', () => { "--client-overlay-errors", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--no-client-overlay-errors"', async () => { @@ -55,7 +55,7 @@ describe('"client" CLI option', () => { "--no-client-overlay-errors", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-overlay-warnings"', async () => { @@ -65,7 +65,7 @@ describe('"client" CLI option', () => { "--client-overlay-warnings", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--no-client-overlay-warnings"', async () => { @@ -75,7 +75,7 @@ describe('"client" CLI option', () => { "--no-client-overlay-warnings", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-logging"', async () => { @@ -86,13 +86,13 @@ describe('"client" CLI option', () => { "verbose", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-progress"', async () => { const { exitCode } = await testBin(["--port", port, "--client-progress"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--no-client-progress"', async () => { @@ -102,13 +102,13 @@ describe('"client" CLI option', () => { "--no-client-progress", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-reconnect"', async () => { const { exitCode } = await testBin(["--port", port, "--client-reconnect"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-reconnect "', async () => { @@ -119,7 +119,7 @@ describe('"client" CLI option', () => { 5, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--no-client-reconnect"', async () => { @@ -129,7 +129,7 @@ describe('"client" CLI option', () => { "--no-client-reconnect", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-web-socket-url"', async () => { @@ -140,7 +140,7 @@ describe('"client" CLI option', () => { "ws://myhost.com:8080/foo/test", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-web-socket-url-protocol"', async () => { @@ -151,7 +151,7 @@ describe('"client" CLI option', () => { "ws:", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-web-socket-url-hostname"', async () => { @@ -162,7 +162,7 @@ describe('"client" CLI option', () => { "0.0.0.0", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-web-socket-url-pathname"', async () => { @@ -173,7 +173,7 @@ describe('"client" CLI option', () => { "/ws", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--client-web-socket-url-port"', async () => { @@ -184,6 +184,6 @@ describe('"client" CLI option', () => { 8080, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); }); diff --git a/test/cli/colors.test.js b/test/cli/colors.test.js index a802ace8c9..a19143439e 100644 --- a/test/cli/colors.test.js +++ b/test/cli/colors.test.js @@ -1,6 +1,6 @@ "use strict"; -const { testBin, normalizeStderr } = require("../helpers/test-bin"); +const { normalizeStderr, testBin } = require("../helpers/test-bin"); const port = require("../ports-map")["cli-colors"]; const colorsDefaultStats = require.resolve( @@ -22,25 +22,25 @@ describe("colors", () => { colorsDefaultStats, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); - expect(stderr).toContain("\x1b["); + expect(stderr).toContain("\u001B["); }); it('should work use colors using "--color"', async () => { const { exitCode, stderr } = await testBin(["--port", port, "--color"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); - expect(stderr).toContain("\x1b["); + expect(stderr).toContain("\u001B["); }); it('should work do not use colors using "--no-color"', async () => { const { exitCode, stderr } = await testBin(["--port", port, "--no-color"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); - expect(stderr).not.toContain("\x1b["); + expect(stderr).not.toContain("\u001B["); }); it("should work use colors using configuration with enabled colors", async () => { @@ -51,9 +51,9 @@ describe("colors", () => { colorsEnabled, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); - expect(stderr).toContain("\x1b["); + expect(stderr).toContain("\u001B["); }); it("should work and do not use colors using configuration with disabled colors", async () => { @@ -64,8 +64,8 @@ describe("colors", () => { colorsDisabled, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); - expect(stderr).not.toContain("\x1b["); + expect(stderr).not.toContain("\u001B["); }); }); diff --git a/test/cli/compress-option.test.js b/test/cli/compress-option.test.js index 7f87d05772..ccd3884350 100644 --- a/test/cli/compress-option.test.js +++ b/test/cli/compress-option.test.js @@ -7,12 +7,12 @@ describe('"compress" CLI option', () => { it('should work using "--compress"', async () => { const { exitCode } = await testBin(["--port", port, "--compress"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--no-compress"', async () => { const { exitCode } = await testBin(["--port", port, "--no-compress"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); }); diff --git a/test/cli/historyApiFallback-option.test.js b/test/cli/historyApiFallback-option.test.js index ac6c09b287..ed267df8ff 100644 --- a/test/cli/historyApiFallback-option.test.js +++ b/test/cli/historyApiFallback-option.test.js @@ -1,6 +1,6 @@ "use strict"; -const { testBin, normalizeStderr } = require("../helpers/test-bin"); +const { normalizeStderr, testBin } = require("../helpers/test-bin"); const port = require("../ports-map")["cli-history-api-fallback"]; describe('"historyApiFallback" CLI option', () => { @@ -12,7 +12,7 @@ describe('"historyApiFallback" CLI option', () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot(); }); @@ -23,7 +23,7 @@ describe('"historyApiFallback" CLI option', () => { "--no-history-api-fallback", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot(); }); }); diff --git a/test/cli/host-option.test.js b/test/cli/host-option.test.js index 341b83f299..7e113c91f3 100644 --- a/test/cli/host-option.test.js +++ b/test/cli/host-option.test.js @@ -1,7 +1,7 @@ "use strict"; -const os = require("os"); -const { testBin, normalizeStderr } = require("../helpers/test-bin"); +const os = require("node:os"); +const { normalizeStderr, testBin } = require("../helpers/test-bin"); const port = require("../ports-map")["cli-host"]; const Server = require("../../lib/Server"); @@ -17,7 +17,7 @@ describe('"host" CLI option', () => { "0.0.0.0", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -29,7 +29,7 @@ describe('"host" CLI option', () => { "::", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -41,7 +41,7 @@ describe('"host" CLI option', () => { "::1", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); @@ -53,7 +53,7 @@ describe('"host" CLI option', () => { "localhost", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); @@ -65,7 +65,7 @@ describe('"host" CLI option', () => { "127.0.0.1", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); @@ -77,11 +77,11 @@ describe('"host" CLI option', () => { "::1", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); - it(`should work using "--host "`, async () => { + it('should work using "--host "', async () => { const { exitCode, stderr } = await testBin([ "--port", port, @@ -89,11 +89,11 @@ describe('"host" CLI option', () => { localIPv4, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); - it.skip(`should work using "--host "`, async () => { + it.skip('should work using "--host "', async () => { const { exitCode, stderr } = await testBin([ "--port", port, @@ -101,7 +101,7 @@ describe('"host" CLI option', () => { localIPv6, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); @@ -113,7 +113,7 @@ describe('"host" CLI option', () => { "local-ip", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); @@ -125,117 +125,115 @@ describe('"host" CLI option', () => { "local-ip", ]); - expect(exitCode).toEqual(0); - jest.spyOn(os, "networkInterfaces").mockImplementation(() => { - return { - lo: [ - { - address: "127.0.0.1", - netmask: "255.0.0.0", - family: "IPv4", - mac: "00:00:00:00:00:00", - internal: true, - cidr: "127.0.0.1/8", - }, - { - address: "::1", - netmask: "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - family: "IPv6", - mac: "00:00:00:00:00:00", - internal: true, - cidr: "::1/128", - scopeid: 0, - }, - ], - enp6s0: [ - { - address: "192.168.1.15", - netmask: "255.255.255.0", - family: "IPv4", - mac: "50:eb:f6:97:9f:6f", - internal: false, - cidr: "192.168.1.15/24", - }, - { - address: "2a01:cb0c:1623:6800:4ff8:723c:1a4b:fe5d", - netmask: "ffff:ffff:ffff:ffff::", - family: "IPv6", - mac: "50:eb:f6:97:9f:6f", - internal: false, - cidr: "2a01:cb0c:1623:6800:4ff8:723c:1a4b:fe5d/64", - scopeid: 0, - }, - { - address: "2a01:cb0c:1623:6800:9acc:408c:ee87:27cf", - netmask: "ffff:ffff:ffff:ffff::", - family: "IPv6", - mac: "50:eb:f6:97:9f:6f", - internal: false, - cidr: "2a01:cb0c:1623:6800:9acc:408c:ee87:27cf/64", - scopeid: 0, - }, - { - address: "fe80::bf2a:e5e2:8f9:4336", - netmask: "ffff:ffff:ffff:ffff::", - family: "IPv6", - mac: "50:eb:f6:97:9f:6f", - internal: false, - cidr: "fe80::bf2a:e5e2:8f9:4336/64", - scopeid: 2, - }, - ], - "br-9bb0264f9b1c": [ - { - address: "172.19.0.1", - netmask: "255.255.0.0", - family: "IPv4", - mac: "02:42:e4:c8:6e:5f", - internal: false, - cidr: "172.19.0.1/16", - }, - { - address: "fe80::42:e4ff:fec8:6e5f", - netmask: "ffff:ffff:ffff:ffff::", - family: "IPv6", - mac: "02:42:e4:c8:6e:5f", - internal: false, - cidr: "fe80::42:e4ff:fec8:6e5f/64", - scopeid: 4, - }, - ], - "br-a52e5d90701f": [ - { - address: "172.18.0.1", - netmask: "255.255.0.0", - family: "IPv4", - mac: "02:42:f6:7e:a2:45", - internal: false, - cidr: "172.18.0.1/16", - }, - { - address: "fe80::42:f6ff:fe7e:a245", - netmask: "ffff:ffff:ffff:ffff::", - family: "IPv6", - mac: "02:42:f6:7e:a2:45", - internal: false, - cidr: "fe80::42:f6ff:fe7e:a245/64", - scopeid: 5, - }, - ], - docker0: [ - { - address: "172.17.0.1", - netmask: "255.255.0.0", - family: "IPv4", - mac: "02:42:3e:89:61:cf", - internal: false, - cidr: "172.17.0.1/16", - }, - ], - }; - }); - expect(stderr.indexOf("172.17.0.1") === -1); - expect(stderr.indexOf("192.168.1.15") > -1); + expect(exitCode).toBe(0); + jest.spyOn(os, "networkInterfaces").mockImplementation(() => ({ + lo: [ + { + address: "127.0.0.1", + netmask: "255.0.0.0", + family: "IPv4", + mac: "00:00:00:00:00:00", + internal: true, + cidr: "127.0.0.1/8", + }, + { + address: "::1", + netmask: "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + family: "IPv6", + mac: "00:00:00:00:00:00", + internal: true, + cidr: "::1/128", + scopeid: 0, + }, + ], + enp6s0: [ + { + address: "192.168.1.15", + netmask: "255.255.255.0", + family: "IPv4", + mac: "50:eb:f6:97:9f:6f", + internal: false, + cidr: "192.168.1.15/24", + }, + { + address: "2a01:cb0c:1623:6800:4ff8:723c:1a4b:fe5d", + netmask: "ffff:ffff:ffff:ffff::", + family: "IPv6", + mac: "50:eb:f6:97:9f:6f", + internal: false, + cidr: "2a01:cb0c:1623:6800:4ff8:723c:1a4b:fe5d/64", + scopeid: 0, + }, + { + address: "2a01:cb0c:1623:6800:9acc:408c:ee87:27cf", + netmask: "ffff:ffff:ffff:ffff::", + family: "IPv6", + mac: "50:eb:f6:97:9f:6f", + internal: false, + cidr: "2a01:cb0c:1623:6800:9acc:408c:ee87:27cf/64", + scopeid: 0, + }, + { + address: "fe80::bf2a:e5e2:8f9:4336", + netmask: "ffff:ffff:ffff:ffff::", + family: "IPv6", + mac: "50:eb:f6:97:9f:6f", + internal: false, + cidr: "fe80::bf2a:e5e2:8f9:4336/64", + scopeid: 2, + }, + ], + "br-9bb0264f9b1c": [ + { + address: "172.19.0.1", + netmask: "255.255.0.0", + family: "IPv4", + mac: "02:42:e4:c8:6e:5f", + internal: false, + cidr: "172.19.0.1/16", + }, + { + address: "fe80::42:e4ff:fec8:6e5f", + netmask: "ffff:ffff:ffff:ffff::", + family: "IPv6", + mac: "02:42:e4:c8:6e:5f", + internal: false, + cidr: "fe80::42:e4ff:fec8:6e5f/64", + scopeid: 4, + }, + ], + "br-a52e5d90701f": [ + { + address: "172.18.0.1", + netmask: "255.255.0.0", + family: "IPv4", + mac: "02:42:f6:7e:a2:45", + internal: false, + cidr: "172.18.0.1/16", + }, + { + address: "fe80::42:f6ff:fe7e:a245", + netmask: "ffff:ffff:ffff:ffff::", + family: "IPv6", + mac: "02:42:f6:7e:a2:45", + internal: false, + cidr: "fe80::42:f6ff:fe7e:a245/64", + scopeid: 5, + }, + ], + docker0: [ + { + address: "172.17.0.1", + netmask: "255.255.0.0", + family: "IPv4", + mac: "02:42:3e:89:61:cf", + internal: false, + cidr: "172.17.0.1/16", + }, + ], + })); + expect(!stderr.includes("172.17.0.1")); + expect(stderr.includes("192.168.1.15")); }); it('should work using "--host local-ipv4"', async () => { @@ -246,7 +244,7 @@ describe('"host" CLI option', () => { "local-ipv4", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); }); diff --git a/test/cli/hot-option.test.js b/test/cli/hot-option.test.js index 5622b5141e..6b525d885a 100644 --- a/test/cli/hot-option.test.js +++ b/test/cli/hot-option.test.js @@ -12,7 +12,7 @@ describe('"hot" CLI option', () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stdout).toContain("webpack/hot/dev-server.js"); }); @@ -24,7 +24,7 @@ describe('"hot" CLI option', () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stdout).not.toContain("webpack/hot/dev-server.js"); }); @@ -36,7 +36,7 @@ describe('"hot" CLI option', () => { }, ); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(stdout).toContain("/hot/only-dev-server.js"); }); }); diff --git a/test/cli/ipc-option.test.js b/test/cli/ipc-option.test.js index 35701f1356..304c05f38d 100644 --- a/test/cli/ipc-option.test.js +++ b/test/cli/ipc-option.test.js @@ -1,26 +1,26 @@ "use strict"; -const path = require("path"); -const os = require("os"); -const { testBin, normalizeStderr } = require("../helpers/test-bin"); +const os = require("node:os"); +const path = require("node:path"); +const { normalizeStderr, testBin } = require("../helpers/test-bin"); describe('"ipc" CLI option', () => { it('should work using "--ipc"', async () => { const { exitCode, stderr } = await testBin(["--ipc"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); it('should work using "--ipc="', async () => { const isWindows = process.platform === "win32"; const pipePrefix = isWindows ? "\\\\.\\pipe\\" : os.tmpdir(); - const pipeName = `webpack-dev-server.cli.sock`; + const pipeName = "webpack-dev-server.cli.sock"; const ipc = path.join(pipePrefix, pipeName); const { exitCode, stderr } = await testBin(["--ipc", ipc]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); }); diff --git a/test/cli/liveReload-option.test.js b/test/cli/liveReload-option.test.js index 716e1bd3a7..53e2b198e8 100644 --- a/test/cli/liveReload-option.test.js +++ b/test/cli/liveReload-option.test.js @@ -7,12 +7,12 @@ describe('"liveReload" CLI option', () => { it('should work using "--live-reload"', async () => { const { exitCode } = await testBin(["--port", port, "--live-reload"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--no-live-reload"', async () => { const { exitCode } = await testBin(["--port", port, "--no-live-reload"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); }); diff --git a/test/cli/open-option.test.js b/test/cli/open-option.test.js index b52cbe7e9e..9cc9b9cd41 100644 --- a/test/cli/open-option.test.js +++ b/test/cli/open-option.test.js @@ -7,7 +7,7 @@ describe('"open" CLI option', () => { it('should work using "--open"', async () => { const { exitCode } = await testBin(["--port", port, "--open"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--open /index.html"', async () => { @@ -18,7 +18,7 @@ describe('"open" CLI option', () => { "/index.html", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--open /first.html second.html"', async () => { @@ -30,13 +30,13 @@ describe('"open" CLI option', () => { "second.html", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--no-open"', async () => { const { exitCode } = await testBin(["--no-open", "--port", port]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--open-reset --open /third.html"', async () => { @@ -48,7 +48,7 @@ describe('"open" CLI option', () => { "/third.html", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--open-reset --open-target "', async () => { @@ -60,7 +60,7 @@ describe('"open" CLI option', () => { "", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--open-reset --open-target /third.html"', async () => { @@ -72,7 +72,7 @@ describe('"open" CLI option', () => { "/third.html", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--open-app-name google-chrome"', async () => { @@ -83,7 +83,7 @@ describe('"open" CLI option', () => { "google-chrome", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--open-app-name-reset --open-app-name firefox"', async () => { @@ -95,7 +95,7 @@ describe('"open" CLI option', () => { "firefox", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--open-target index.html"', async () => { @@ -106,7 +106,7 @@ describe('"open" CLI option', () => { "index.html", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--open-target-reset --open-target first.html"', async () => { @@ -118,7 +118,7 @@ describe('"open" CLI option', () => { "first.html", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--open-target /first.html second.html"', async () => { @@ -130,7 +130,7 @@ describe('"open" CLI option', () => { "second.html", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--open-target /index.html --open-app-name google-chrome"', async () => { @@ -143,6 +143,6 @@ describe('"open" CLI option', () => { "google-chrome", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); }); diff --git a/test/cli/port-option.test.js b/test/cli/port-option.test.js index 3d85f35ff8..b771e7f280 100644 --- a/test/cli/port-option.test.js +++ b/test/cli/port-option.test.js @@ -1,20 +1,20 @@ "use strict"; -const { testBin, normalizeStderr } = require("../helpers/test-bin"); +const { normalizeStderr, testBin } = require("../helpers/test-bin"); const port = require("../ports-map")["cli-port-option"]; describe('"port" CLI option', () => { it('should work using "--port "', async () => { const { exitCode, stderr } = await testBin(["--port", port]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); - it(`should work using "--port auto"`, async () => { + it('should work using "--port auto"', async () => { const { exitCode, stderr } = await testBin(["--port", "auto"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); }); diff --git a/test/cli/server-option.test.js b/test/cli/server-option.test.js index a54b476383..4f5d709284 100644 --- a/test/cli/server-option.test.js +++ b/test/cli/server-option.test.js @@ -1,9 +1,9 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const { rimraf } = require("rimraf"); const Server = require("../../lib/Server"); -const { testBin, normalizeStderr } = require("../helpers/test-bin"); +const { normalizeStderr, testBin } = require("../helpers/test-bin"); const port = require("../ports-map")["cli-server"]; const httpsCertificateDirectory = path.resolve( @@ -26,7 +26,7 @@ describe('"server" CLI options', () => { "http", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect( normalizeStderr(stderr, { ipv6: true, https: false }), ).toMatchSnapshot(); @@ -40,7 +40,7 @@ describe('"server" CLI options', () => { "https", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect( normalizeStderr(stderr, { ipv6: true, https: true }), ).toMatchSnapshot(); @@ -58,7 +58,7 @@ describe('"server" CLI options', () => { "spdy", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect( normalizeStderr(stderr, { ipv6: true, https: true }), ).toMatchSnapshot(); @@ -86,7 +86,7 @@ describe('"server" CLI options', () => { cert, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect( normalizeStderr(stderr, { ipv6: true, https: true }), ).toMatchSnapshot(); @@ -116,7 +116,7 @@ describe('"server" CLI options', () => { ca, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect( normalizeStderr(stderr, { ipv6: true, https: true }), ).toMatchSnapshot(); @@ -150,7 +150,7 @@ describe('"server" CLI options', () => { ca, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect( normalizeStderr(stderr, { ipv6: true, https: true }), ).toMatchSnapshot(); @@ -178,7 +178,7 @@ describe('"server" CLI options', () => { cert, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect( normalizeStderr(stderr, { ipv6: true, https: true }), ).toMatchSnapshot(); @@ -193,7 +193,7 @@ describe('"server" CLI options', () => { "--server-options-request-cert", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect( normalizeStderr(stderr, { ipv6: true, https: true }), ).toMatchSnapshot(); @@ -208,7 +208,7 @@ describe('"server" CLI options', () => { "--no-server-options-request-cert", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect( normalizeStderr(stderr, { ipv6: true, https: true }), ).toMatchSnapshot(); diff --git a/test/cli/static-option.test.js b/test/cli/static-option.test.js index 5a923ae94b..66ccd5ec67 100644 --- a/test/cli/static-option.test.js +++ b/test/cli/static-option.test.js @@ -1,13 +1,13 @@ "use strict"; -const { testBin, normalizeStderr } = require("../helpers/test-bin"); +const { normalizeStderr, testBin } = require("../helpers/test-bin"); const port = require("../ports-map")["cli-static"]; describe('"static" CLI option', () => { it('should work using "--static"', async () => { const { exitCode, stderr } = await testBin(["--port", port, "--static"]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -19,7 +19,7 @@ describe('"static" CLI option', () => { "new-static", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -33,7 +33,7 @@ describe('"static" CLI option', () => { "other-static", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -46,7 +46,7 @@ describe('"static" CLI option', () => { "new-static-after-reset", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -59,7 +59,7 @@ describe('"static" CLI option', () => { "new-static-directory", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -71,7 +71,7 @@ describe('"static" CLI option', () => { "static-dir", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -83,7 +83,7 @@ describe('"static" CLI option', () => { "/public", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -96,7 +96,7 @@ describe('"static" CLI option', () => { "/new-public", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -107,7 +107,7 @@ describe('"static" CLI option', () => { "--static-serve-index", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -118,7 +118,7 @@ describe('"static" CLI option', () => { "--no-static-serve-index", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -129,7 +129,7 @@ describe('"static" CLI option', () => { "--static-watch", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -140,7 +140,7 @@ describe('"static" CLI option', () => { "--no-static-watch", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); }); diff --git a/test/cli/watchFiles-option.test.js b/test/cli/watchFiles-option.test.js index 447dc91466..93eeebfe78 100644 --- a/test/cli/watchFiles-option.test.js +++ b/test/cli/watchFiles-option.test.js @@ -1,7 +1,7 @@ "use strict"; -const path = require("path"); -const { testBin, normalizeStderr } = require("../helpers/test-bin"); +const path = require("node:path"); +const { normalizeStderr, testBin } = require("../helpers/test-bin"); const port = require("../ports-map")["cli-watch-files"]; describe('"watchFiles" CLI option', () => { @@ -15,7 +15,7 @@ describe('"watchFiles" CLI option', () => { watchDirectory, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -35,7 +35,7 @@ describe('"watchFiles" CLI option', () => { watchOtherDirectory, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); @@ -50,7 +50,7 @@ describe('"watchFiles" CLI option', () => { watchDirectory, ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr"); }); }); diff --git a/test/cli/webSocketServer-option.test.js b/test/cli/webSocketServer-option.test.js index 781453bc29..ec383cd767 100644 --- a/test/cli/webSocketServer-option.test.js +++ b/test/cli/webSocketServer-option.test.js @@ -12,7 +12,7 @@ describe('"webSocketServer" CLI option', () => { "ws", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--web-socket-server-type sockjs"', async () => { @@ -23,7 +23,7 @@ describe('"webSocketServer" CLI option', () => { "sockjs", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); it('should work using "--no-web-socket-server"', async () => { @@ -33,6 +33,6 @@ describe('"webSocketServer" CLI option', () => { "--no-web-socket-server", ]); - expect(exitCode).toEqual(0); + expect(exitCode).toBe(0); }); }); diff --git a/test/client/ReactErrorBoundary.test.js b/test/client/ReactErrorBoundary.test.js index 03f27f0efb..0313386b9c 100644 --- a/test/client/ReactErrorBoundary.test.js +++ b/test/client/ReactErrorBoundary.test.js @@ -7,27 +7,23 @@ const { createOverlay } = require("../../client-src/overlay"); describe("createOverlay", () => { - const originalDocument = global.document; - const originalWindow = global.window; + const originalDocument = globalThis.document; + const originalWindow = globalThis.window; beforeEach(() => { - global.document = { - createElement: jest.fn(() => { - return { - style: {}, - appendChild: jest.fn(), - addEventListener: jest.fn(), - contentDocument: { - createElement: jest.fn(() => { - return { style: {}, appendChild: jest.fn() }; - }), - body: { appendChild: jest.fn() }, - }, - }; - }), + globalThis.document = { + createElement: jest.fn(() => ({ + style: {}, + appendChild: jest.fn(), + addEventListener: jest.fn(), + contentDocument: { + createElement: jest.fn(() => ({ style: {}, appendChild: jest.fn() })), + body: { appendChild: jest.fn() }, + }, + })), body: { appendChild: jest.fn(), removeChild: jest.fn() }, }; - global.window = { + globalThis.window = { // Keep addEventListener mocked for other potential uses addEventListener: jest.fn(), removeEventListener: jest.fn(), @@ -40,8 +36,8 @@ describe("createOverlay", () => { }); afterEach(() => { - global.document = originalDocument; - global.window = originalWindow; + globalThis.document = originalDocument; + globalThis.window = originalWindow; jest.useRealTimers(); jest.clearAllMocks(); }); @@ -70,7 +66,7 @@ describe("createOverlay", () => { error: reactError, message: reactError.message, }); - window.dispatchEvent(errorEvent); + globalThis.dispatchEvent(errorEvent); expect(showOverlayMock).not.toHaveBeenCalled(); showOverlayMock.mockRestore(); @@ -94,7 +90,7 @@ describe("createOverlay", () => { error: regularError, message: "Regular test error message", }); - window.dispatchEvent(errorEvent); + globalThis.dispatchEvent(errorEvent); expect(showOverlayMock).toHaveBeenCalledWith({ type: "RUNTIME_ERROR", @@ -117,7 +113,7 @@ describe("createOverlay", () => { error: null, message: "error", }); - window.dispatchEvent(errorEvent); + globalThis.dispatchEvent(errorEvent); expect(showOverlayMock).toHaveBeenCalledWith({ type: "RUNTIME_ERROR", @@ -144,7 +140,7 @@ describe("createOverlay", () => { error: regularError, message: "Regular test error message", }); - window.dispatchEvent(errorEvent); + globalThis.dispatchEvent(errorEvent); expect(showOverlayMock).toHaveBeenCalledWith({ type: "RUNTIME_ERROR", @@ -171,7 +167,7 @@ describe("createOverlay", () => { error: regularError, message: "Regular test error message", }); - window.dispatchEvent(errorEvent); + globalThis.dispatchEvent(errorEvent); expect(showOverlayMock).not.toHaveBeenCalled(); showOverlayMock.mockRestore(); @@ -188,7 +184,7 @@ describe("createOverlay", () => { error: reactInternalError, message: "React internal error", }); - window.dispatchEvent(errorEvent); + globalThis.dispatchEvent(errorEvent); expect(showOverlayMock).not.toHaveBeenCalled(); showOverlayMock.mockRestore(); @@ -203,7 +199,7 @@ describe("createOverlay", () => { const rejectionEvent = new Event("unhandledrejection"); rejectionEvent.reason = rejectionReason; - window.dispatchEvent(rejectionEvent); + globalThis.dispatchEvent(rejectionEvent); expect(showOverlayMock).toHaveBeenCalledWith({ type: "RUNTIME_ERROR", @@ -223,7 +219,7 @@ describe("createOverlay", () => { const showOverlayMock = jest.spyOn(overlay, "send"); const rejectionEvent = new Event("unhandledrejection"); rejectionEvent.reason = "some reason"; - window.dispatchEvent(rejectionEvent); + globalThis.dispatchEvent(rejectionEvent); expect(showOverlayMock).toHaveBeenCalledWith({ type: "RUNTIME_ERROR", diff --git a/test/client/bundle.test.js b/test/client/bundle.test.js index 13f5779830..1808fe5e84 100644 --- a/test/client/bundle.test.js +++ b/test/client/bundle.test.js @@ -1,8 +1,8 @@ "use strict"; -const webpack = require("webpack"); const acorn = require("acorn"); const request = require("supertest"); +const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/simple-config/webpack.config"); const port = require("../ports-map").bundle; diff --git a/test/client/clients/SockJSClient.test.js b/test/client/clients/SockJSClient.test.js index 363c84ab06..08e8a594c6 100644 --- a/test/client/clients/SockJSClient.test.js +++ b/test/client/clients/SockJSClient.test.js @@ -4,7 +4,7 @@ "use strict"; -const http = require("http"); +const http = require("node:http"); const express = require("express"); const sockjs = require("sockjs"); const port = require("../../ports-map")["sockjs-client"]; @@ -19,6 +19,7 @@ describe("SockJSClient", () => { const SockJSClient = require("../../../client-src/clients/SockJSClient").default; const { log } = require("../../../client-src/utils/log"); + let consoleMock; let socketServer; let server; @@ -70,7 +71,7 @@ describe("SockJSClient", () => { client.sock.onerror(testError); - expect(log.error.mock.calls.length).toEqual(1); + expect(log.error.mock.calls).toHaveLength(1); expect(log.error.mock.calls[0]).toEqual([testError]); setTimeout(() => { diff --git a/test/client/clients/WebsocketClient.test.js b/test/client/clients/WebsocketClient.test.js index 8af1345be0..de113abb2c 100644 --- a/test/client/clients/WebsocketClient.test.js +++ b/test/client/clients/WebsocketClient.test.js @@ -5,7 +5,7 @@ "use strict"; -const http = require("http"); +const http = require("node:http"); const express = require("express"); const ws = require("ws"); const port = require("../../ports-map")["web-socket-client"]; @@ -65,7 +65,7 @@ describe("WebsocketClient", () => { client.client.onerror(testError); - expect(log.error.mock.calls.length).toEqual(1); + expect(log.error.mock.calls).toHaveLength(1); expect(log.error.mock.calls[0]).toEqual([testError]); setTimeout(() => { diff --git a/test/client/index.test.js b/test/client/index.test.js index f45f7bbf77..9f305318ac 100644 --- a/test/client/index.test.js +++ b/test/client/index.test.js @@ -11,11 +11,11 @@ describe("index", () => { let sendMessage; let onSocketMessage; const locationValue = self.location; - const resourceQueryValue = global.__resourceQuery; + const resourceQueryValue = globalThis.__resourceQuery; beforeEach(() => { - global.__resourceQuery = "?mock-url"; - global.__webpack_hash__ = "mock-hash"; + globalThis.__resourceQuery = "?mock-url"; + globalThis.__webpack_hash__ = "mock-hash"; // log jest.setMock("../../client-src/utils/log.js", { @@ -38,16 +38,17 @@ describe("index", () => { // overlay jest.setMock("../../client-src/overlay.js", { - createOverlay: () => { - return { - send, - }; - }, - formatProblem: (item) => { - return { header: "HEADER warning", body: `BODY: ${item}` }; - }, + createOverlay: () => ({ + send, + }), + formatProblem: (item) => ({ + header: "HEADER warning", + body: `BODY: ${item}`, + }), }); + const { createOverlay } = require("../../client-src/overlay"); + overlay = createOverlay(); // sendMessage @@ -55,31 +56,31 @@ describe("index", () => { sendMessage = require("../../client-src/utils/sendMessage"); // issue: https://github.com/jsdom/jsdom/issues/2112 - delete window.location; + delete globalThis.location; - window.location = { ...locationValue, reload: jest.fn() }; + globalThis.location = { ...locationValue, reload: jest.fn() }; require("../../client-src"); onSocketMessage = socket.mock.calls[0][1]; }); afterEach(() => { - global.__resourceQuery = resourceQueryValue; - Object.assign(self, locationValue); + globalThis.__resourceQuery = resourceQueryValue; + Object.assign(globalThis, locationValue); jest.resetAllMocks(); jest.resetModules(); }); - test("should set arguments into socket function", () => { + it("should set arguments into socket function", () => { expect(socket.mock.calls[0]).toMatchSnapshot(); }); - test("should run onSocketMessage['still-ok']", () => { + it("should run onSocketMessage['still-ok']", () => { onSocketMessage["still-ok"](); expect(log.log.info.mock.calls[1][0]).toMatchSnapshot(); expect(sendMessage.mock.calls[0][0]).toMatchSnapshot(); - expect(overlay.send).not.toBeCalledWith({ type: "DISMISS" }); + expect(overlay.send).not.toHaveBeenCalledWith({ type: "DISMISS" }); // change flags onSocketMessage.overlay(true); @@ -88,7 +89,7 @@ describe("index", () => { expect(overlay.send).toHaveBeenCalledWith({ type: "DISMISS" }); }); - test("should run onSocketMessage.progress and onSocketMessage['progress-update']", () => { + it("should run onSocketMessage.progress and onSocketMessage['progress-update']", () => { onSocketMessage.progress(false); onSocketMessage["progress-update"]({ msg: "mock-msg", @@ -106,7 +107,7 @@ describe("index", () => { expect(log.log.info.mock.calls[1][0]).toMatchSnapshot(); }); - test("should run onSocketMessage.progress and onSocketMessage['progress-update'] and log plugin name", () => { + it("should run onSocketMessage.progress and onSocketMessage['progress-update'] and log plugin name", () => { onSocketMessage.progress(false); onSocketMessage["progress-update"]({ msg: "mock-msg", @@ -126,7 +127,7 @@ describe("index", () => { expect(log.log.info.mock.calls[1][0]).toMatchSnapshot(); }); - test("should run onSocketMessage.ok", () => { + it("should run onSocketMessage.ok", () => { onSocketMessage.ok(); expect(sendMessage.mock.calls[0][0]).toMatchSnapshot(); @@ -136,25 +137,24 @@ describe("index", () => { const res = onSocketMessage.ok(); - // eslint-disable-next-line no-undefined - expect(res).toEqual(undefined); + expect(res).toBeUndefined(); }); - test("should run onSocketMessage['static-changed']", () => { + it("should run onSocketMessage['static-changed']", () => { onSocketMessage["static-changed"](); expect(log.log.info.mock.calls[1][0]).toMatchSnapshot(); - expect(self.location.reload).toBeCalled(); + expect(self.location.reload).toHaveBeenCalled(); }); - test("should run onSocketMessage['static-changed'](file)", () => { + it("should run onSocketMessage['static-changed'](file)", () => { onSocketMessage["static-changed"]("/static/assets/index.html"); expect(log.log.info.mock.calls[1][0]).toMatchSnapshot(); - expect(self.location.reload).toBeCalled(); + expect(self.location.reload).toHaveBeenCalled(); }); - test("should run onSocketMessage.warnings", () => { + it("should run onSocketMessage.warnings", () => { onSocketMessage.warnings(["warn1", "\u001B[4mwarn2\u001B[0m", "warn3"]); expect(log.log.warn.mock.calls[0][0]).toMatchSnapshot(); @@ -173,11 +173,11 @@ describe("index", () => { }); }); - test("should parse overlay options from resource query", () => { + it("should parse overlay options from resource query", () => { jest.isolateModules(() => { // Pass JSON config with warnings disabled - global.__resourceQuery = `?overlay=${encodeURIComponent( - `{"warnings": false}`, + globalThis.__resourceQuery = `?overlay=${encodeURIComponent( + '{"warnings": false}', )}`; overlay.send.mockReset(); socket.mockReset(); @@ -185,10 +185,10 @@ describe("index", () => { onSocketMessage = socket.mock.calls[0][1]; onSocketMessage.warnings(["warn1"]); - expect(overlay.send).not.toBeCalled(); + expect(overlay.send).not.toHaveBeenCalled(); onSocketMessage.errors(["error1"]); - expect(overlay.send).toBeCalledTimes(1); + expect(overlay.send).toHaveBeenCalledTimes(1); expect(overlay.send).toHaveBeenCalledWith({ type: "BUILD_ERROR", level: "error", @@ -198,8 +198,8 @@ describe("index", () => { jest.isolateModules(() => { // Pass JSON config with errors disabled - global.__resourceQuery = `?overlay=${encodeURIComponent( - `{"errors": false}`, + globalThis.__resourceQuery = `?overlay=${encodeURIComponent( + '{"errors": false}', )}`; overlay.send.mockReset(); socket.mockReset(); @@ -207,10 +207,10 @@ describe("index", () => { onSocketMessage = socket.mock.calls[0][1]; onSocketMessage.errors(["error1"]); - expect(overlay.send).not.toBeCalled(); + expect(overlay.send).not.toHaveBeenCalled(); onSocketMessage.warnings(["warn1"]); - expect(overlay.send).toBeCalledTimes(1); + expect(overlay.send).toHaveBeenCalledTimes(1); expect(overlay.send).toHaveBeenCalledWith({ type: "BUILD_ERROR", level: "warning", @@ -220,14 +220,14 @@ describe("index", () => { jest.isolateModules(() => { // Use simple boolean - global.__resourceQuery = "?overlay=true"; + globalThis.__resourceQuery = "?overlay=true"; socket.mockReset(); overlay.send.mockReset(); require("../../client-src"); onSocketMessage = socket.mock.calls[0][1]; onSocketMessage.warnings(["warn2"]); - expect(overlay.send).toBeCalledTimes(1); + expect(overlay.send).toHaveBeenCalledTimes(1); expect(overlay.send).toHaveBeenLastCalledWith({ type: "BUILD_ERROR", level: "warning", @@ -235,7 +235,7 @@ describe("index", () => { }); onSocketMessage.errors(["error2"]); - expect(overlay.send).toBeCalledTimes(2); + expect(overlay.send).toHaveBeenCalledTimes(2); expect(overlay.send).toHaveBeenLastCalledWith({ type: "BUILD_ERROR", level: "error", @@ -244,20 +244,20 @@ describe("index", () => { }); }); - test("should run onSocketMessage.error", () => { + it("should run onSocketMessage.error", () => { onSocketMessage.error("error!!"); expect(log.log.error.mock.calls[0][0]).toMatchSnapshot(); }); - test("should run onSocketMessage.close", () => { + it("should run onSocketMessage.close", () => { onSocketMessage.close(); expect(log.log.info.mock.calls[1][0]).toMatchSnapshot(); expect(sendMessage.mock.calls[0][0]).toMatchSnapshot(); }); - test("should run onSocketMessage.close (hot enabled)", () => { + it("should run onSocketMessage.close (hot enabled)", () => { // enabling hot onSocketMessage.hot(); onSocketMessage.close(); @@ -266,7 +266,7 @@ describe("index", () => { expect(sendMessage.mock.calls[0][0]).toMatchSnapshot(); }); - test("should run onSocketMessage.close (liveReload enabled)", () => { + it("should run onSocketMessage.close (liveReload enabled)", () => { // enabling liveReload onSocketMessage.liveReload(); onSocketMessage.close(); diff --git a/test/client/socket-helper.test.js b/test/client/socket-helper.test.js index a4bed4130d..504fbfb613 100644 --- a/test/client/socket-helper.test.js +++ b/test/client/socket-helper.test.js @@ -47,7 +47,7 @@ describe("socket", () => { const socket = require("../../client/socket").default; - global.__webpack_dev_server_client__ = + globalThis.__webpack_dev_server_client__ = require("../../client/clients/WebSocketClient").default; const mockHandler = jest.fn(); @@ -57,7 +57,7 @@ describe("socket", () => { }); const mockClientInstance = - global.__webpack_dev_server_client__.mock.instances[0]; + globalThis.__webpack_dev_server_client__.mock.instances[0]; // this simulates receiving a message from the server and passing it // along to the callback of onMessage @@ -70,7 +70,7 @@ describe("socket", () => { ); expect( - global.__webpack_dev_server_client__.mock.calls[0], + globalThis.__webpack_dev_server_client__.mock.calls[0], ).toMatchSnapshot(); expect(mockClientInstance.onOpen.mock.calls).toMatchSnapshot(); expect(mockClientInstance.onClose.mock.calls).toMatchSnapshot(); @@ -82,12 +82,14 @@ describe("socket", () => { const socket = require("../../client/socket").default; const nonInitializedInstance = require("../../client/socket").client; - expect(nonInitializedInstance).toBe(null); + + expect(nonInitializedInstance).toBeNull(); socket("my.url", {}); const initializedInstance = require("../../client/socket").client; - expect(initializedInstance).not.toBe(null); + + expect(initializedInstance).not.toBeNull(); expect(typeof initializedInstance.onClose).toBe("function"); expect(typeof initializedInstance.onMessage).toBe("function"); expect(typeof initializedInstance.onOpen).toBe("function"); diff --git a/test/client/utils/createSocketURL.test.js b/test/client/utils/createSocketURL.test.js index 4fbc4ec940..3170d8fa62 100644 --- a/test/client/utils/createSocketURL.test.js +++ b/test/client/utils/createSocketURL.test.js @@ -4,8 +4,8 @@ "use strict"; -describe("'createSocketURL' function ", () => { - global.__webpack_hash__ = "hash"; +describe("'createSocketURL' function", () => { + globalThis.__webpack_hash__ = "hash"; const samples = [ // // __resourceQuery, location and socket URL @@ -104,9 +104,9 @@ describe("'createSocketURL' function ", () => { [null, "file://localhost/", "ws://localhost/ws"], ]; - samples.forEach(([__resourceQuery, location, expected]) => { - test(`should return '${expected}' socket URL when '__resourceQuery' is '${__resourceQuery}' and 'self.location' is '${location}'`, () => { - global.__resourceQuery = __resourceQuery; + for (const [__resourceQuery, location, expected] of samples) { + it(`should return '${expected}' socket URL when '__resourceQuery' is '${__resourceQuery}' and 'self.location' is '${location}'`, () => { + globalThis.__resourceQuery = __resourceQuery; if (__resourceQuery === null) { Object.defineProperty(document, "currentScript", { @@ -116,14 +116,15 @@ describe("'createSocketURL' function ", () => { } const client = require("../../../client-src/index"); - const createSocketURL = client.createSocketURL; - const parseURL = client.parseURL; + + const { createSocketURL } = client; + const { parseURL } = client; const selfLocation = new URL(location); - delete window.location; + delete globalThis.location; - window.location = selfLocation; + globalThis.location = selfLocation; const parsedURL = parseURL(__resourceQuery); @@ -138,5 +139,5 @@ describe("'createSocketURL' function ", () => { }); jest.resetModules(); - }); + } }); diff --git a/test/client/utils/getCurrentScriptSource.test.js b/test/client/utils/getCurrentScriptSource.test.js index fc51e9fc46..8eca65c0bd 100644 --- a/test/client/utils/getCurrentScriptSource.test.js +++ b/test/client/utils/getCurrentScriptSource.test.js @@ -8,8 +8,8 @@ describe("'getCurrentScriptSource' function", () => { let getCurrentScriptSource; beforeEach(() => { - global.__webpack_hash__ = "mock-hash"; - global.__resourceQuery = "?protocol=ws&hostname=0.0.0.0"; + globalThis.__webpack_hash__ = "mock-hash"; + globalThis.__resourceQuery = "?protocol=ws&hostname=0.0.0.0"; getCurrentScriptSource = require("../../../client-src/index").getCurrentScriptSource; @@ -17,7 +17,6 @@ describe("'getCurrentScriptSource' function", () => { afterEach(() => { Object.defineProperty(document, "currentScript", { - // eslint-disable-next-line no-undefined value: undefined, writable: true, }); @@ -27,7 +26,7 @@ describe("'getCurrentScriptSource' function", () => { }); }); - test("should fail when 'document.currentScript' doesn't exist and no 'script' tags", () => { + it("should fail when 'document.currentScript' doesn't exist and no 'script' tags", () => { try { getCurrentScriptSource(); } catch (error) { @@ -35,7 +34,7 @@ describe("'getCurrentScriptSource' function", () => { } }); - test("should return src when 'document.currentScript' exists", () => { + it("should return src when 'document.currentScript' exists", () => { const elm = document.createElement("script"); elm.setAttribute("src", "foo"); @@ -44,12 +43,11 @@ describe("'getCurrentScriptSource' function", () => { value: elm, }); - expect(getCurrentScriptSource()).toEqual("foo"); + expect(getCurrentScriptSource()).toBe("foo"); }); - test("should fail when 'document.scripts' doesn't exist and no scripts", () => { + it("should fail when 'document.scripts' doesn't exist and no scripts", () => { Object.defineProperty(document, "scripts", { - // eslint-disable-next-line no-undefined value: undefined, writable: true, }); @@ -61,7 +59,7 @@ describe("'getCurrentScriptSource' function", () => { } }); - test("should return the 'src' attribute of the last 'script' tag", () => { + it("should return the 'src' attribute of the last 'script' tag", () => { const elements = ["foo", "bar"].map((src) => { const element = document.createElement("script"); @@ -74,10 +72,10 @@ describe("'getCurrentScriptSource' function", () => { value: elements, }); - expect(getCurrentScriptSource()).toEqual("bar"); + expect(getCurrentScriptSource()).toBe("bar"); }); - test("should fail when no scripts with the 'scr' attribute", () => { + it("should fail when no scripts with the 'scr' attribute", () => { const elements = ["foo", "bar"].map(() => document.createElement("script")); Object.defineProperty(document, "scripts", { diff --git a/test/client/utils/log.test.js b/test/client/utils/log.test.js index 8ca0ff433c..53c0fb64a5 100644 --- a/test/client/utils/log.test.js +++ b/test/client/utils/log.test.js @@ -23,23 +23,23 @@ describe("'log' function", () => { logMock.configureDefaultLogger.mockClear(); }); - test("should set info as the default level and create logger", () => { - const getLogger = logMock.getLogger; - const configureDefaultLogger = logMock.configureDefaultLogger; + it("should set info as the default level and create logger", () => { + const { getLogger } = logMock; + const { configureDefaultLogger } = logMock; - expect(configureDefaultLogger).toBeCalled(); + expect(configureDefaultLogger).toHaveBeenCalled(); expect(configureDefaultLogger.mock.calls[0][0]).toEqual({ level: "info", }); - expect(getLogger).toBeCalled(); - expect(getLogger.mock.calls[0][0]).toEqual("webpack-dev-server"); + expect(getLogger).toHaveBeenCalled(); + expect(getLogger.mock.calls[0][0]).toBe("webpack-dev-server"); }); - test("should set log level via setLogLevel", () => { - ["none", "error", "warn", "info", "log", "verbose"].forEach((level) => { + it("should set log level via setLogLevel", () => { + for (const level of ["none", "error", "warn", "info", "log", "verbose"]) { setLogLevel(level); - }); + } expect(logMock.configureDefaultLogger.mock.calls).toMatchSnapshot(); }); diff --git a/test/client/utils/sendMessage.test.js b/test/client/utils/sendMessage.test.js index 6782d6fc38..3bfdb588d5 100644 --- a/test/client/utils/sendMessage.test.js +++ b/test/client/utils/sendMessage.test.js @@ -11,12 +11,12 @@ describe("'sendMessage' function", () => { jest.resetAllMocks(); }); - test("should run self.postMessage", () => { - self.postMessage = jest.fn(); + it("should run self.postMessage", () => { + jest.spyOn(globalThis, "postMessage").mockImplementation(); sendMessage("foo", "bar"); - expect(self.postMessage).toBeCalled(); + expect(self.postMessage).toHaveBeenCalled(); expect(self.postMessage.mock.calls[0]).toMatchSnapshot(); }); }); diff --git a/test/e2e/allowed-hosts.test.js b/test/e2e/allowed-hosts.test.js index 2809c6b7d5..3c469f4b1c 100644 --- a/test/e2e/allowed-hosts.test.js +++ b/test/e2e/allowed-hosts.test.js @@ -1,8 +1,8 @@ "use strict"; const express = require("express"); -const webpack = require("webpack"); const { createProxyMiddleware } = require("http-proxy-middleware"); +const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/client-config/webpack.config"); const runBrowser = require("../helpers/run-browser"); @@ -1848,13 +1848,13 @@ describe("allowed hosts", () => { waitUntil: "networkidle0", }); - tests.forEach((test) => { + for (const test of tests) { const headers = { host: test }; if (!server.isValidHost(headers, "host")) { throw new Error("Validation didn't fail"); } - }); + } expect(response.status()).toMatchSnapshot("response status"); @@ -1898,13 +1898,13 @@ describe("allowed hosts", () => { "subdomain.example.com:80", ]; - tests.forEach((test) => { + for (const test of tests) { const headers = { host: test }; if (!server.isValidHost(headers, "host")) { throw new Error("Validation didn't fail"); } - }); + } expect(response.status()).toMatchSnapshot("response status"); diff --git a/test/e2e/api.test.js b/test/e2e/api.test.js index 21f8cb3608..b86c19d144 100644 --- a/test/e2e/api.test.js +++ b/test/e2e/api.test.js @@ -1,6 +1,6 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/client-config/webpack.config"); @@ -72,7 +72,7 @@ describe("API", () => { }); describe("latest async API", () => { - it(`should work with async API`, async () => { + it("should work with async API", async () => { const compiler = webpack(config); const server = new Server({ port }, compiler); @@ -108,7 +108,7 @@ describe("API", () => { } }); - it(`should work with callback API`, async () => { + it("should work with callback API", async () => { const compiler = webpack(config); const server = new Server({ port }, compiler); @@ -152,7 +152,7 @@ describe("API", () => { } }); - it(`should catch errors within startCallback`, async () => { + it("should catch errors within startCallback", async () => { const compiler = webpack(config); const server = new Server( { port, static: "https://absolute-url.com/somewhere" }, @@ -161,7 +161,7 @@ describe("API", () => { await new Promise((resolve) => { server.startCallback((err) => { - expect(err.message).toEqual( + expect(err.message).toBe( "Using a URL as static.directory is not supported", ); resolve(); @@ -175,7 +175,7 @@ describe("API", () => { }); }); - it(`should work when using configured manually`, async () => { + it("should work when using configured manually", async () => { const compiler = webpack({ ...config, entry: [ @@ -221,7 +221,7 @@ describe("API", () => { } }); - it(`should work and allow to rerun dev server multiple times`, async () => { + it("should work and allow to rerun dev server multiple times", async () => { const compiler = webpack(config); const server = new Server({ port }, compiler); @@ -436,7 +436,7 @@ describe("API", () => { const freePort = await Server.getFreePort(9082); - expect(freePort).toEqual(9082); + expect(freePort).toBe(9082); }); it("should return the port when the port is `null`", async () => { @@ -445,7 +445,10 @@ describe("API", () => { process.env.WEBPACK_DEV_SERVER_PORT_RETRY = retryCount; try { await createDummyServers(retryCount); - const basePort = parseInt(process.env.WEBPACK_DEV_SERVER_BASE_PORT, 10); + const basePort = Number.parseInt( + process.env.WEBPACK_DEV_SERVER_BASE_PORT, + 10, + ); const freePort = await Server.getFreePort(null); expect(freePort).toEqual(basePort + retryCount); @@ -517,8 +520,11 @@ describe("API", () => { process.env.WEBPACK_DEV_SERVER_PORT_RETRY = retryCount; try { await createDummyServers(retryCount); - const basePort = parseInt(process.env.WEBPACK_DEV_SERVER_BASE_PORT, 10); - // eslint-disable-next-line no-undefined + const basePort = Number.parseInt( + process.env.WEBPACK_DEV_SERVER_BASE_PORT, + 10, + ); + const freePort = await Server.getFreePort(undefined); expect(freePort).toEqual(basePort + retryCount); @@ -591,7 +597,10 @@ describe("API", () => { try { await createDummyServers(retryCount); - const basePort = parseInt(process.env.WEBPACK_DEV_SERVER_BASE_PORT, 10); + const basePort = Number.parseInt( + process.env.WEBPACK_DEV_SERVER_BASE_PORT, + 10, + ); const freePort = await Server.getFreePort(); expect(freePort).toEqual(basePort + retryCount); @@ -665,7 +674,10 @@ describe("API", () => { try { await createDummyServers(retryCount); - const basePort = parseInt(process.env.WEBPACK_DEV_SERVER_BASE_PORT, 10); + const basePort = Number.parseInt( + process.env.WEBPACK_DEV_SERVER_BASE_PORT, + 10, + ); const freePort = await Server.getFreePort(); expect(freePort).toEqual(basePort + retryCount); @@ -733,7 +745,7 @@ describe("API", () => { }); it("should retry finding the port when serial ports are busy", async () => { - const basePort = parseInt( + const basePort = Number.parseInt( process.env.WEBPACK_DEV_SERVER_TEST_BASE_PORT || 30000, 10, ); @@ -857,13 +869,13 @@ describe("API", () => { const compiler = webpack(config); const server = new Server(options, compiler); - tests.forEach((test) => { + for (const test of tests) { const headers = { host: test }; if (!server.isValidHost(headers, "host")) { throw new Error("Validation didn't pass"); } - }); + } }); it('should allow URLs with scheme for checking origin when the "option.client.webSocketURL" is object', async () => { diff --git a/test/e2e/app.test.js b/test/e2e/app.test.js index c1ae5df786..767fb5b980 100644 --- a/test/e2e/app.test.js +++ b/test/e2e/app.test.js @@ -1,7 +1,7 @@ "use strict"; -const fs = require("fs"); -const path = require("path"); +const fs = require("node:fs"); +const path = require("node:path"); const webpack = require("webpack"); const wdm = require("webpack-dev-middleware"); const Server = require("../../lib/Server"); @@ -121,8 +121,7 @@ describe("app option", () => { setupMiddlewares: typeof setupMiddlewares !== "undefined" ? setupMiddlewares - : // eslint-disable-next-line no-undefined - undefined, + : undefined, }, compiler, ); @@ -171,20 +170,18 @@ describe("app option", () => { server === "http2" || (server.options && server.options.allowHTTP1) ) { - expect(HTTPVersion).toEqual("h2"); + expect(HTTPVersion).toBe("h2"); } else { - expect(HTTPVersion).toEqual("http/1.1"); + expect(HTTPVersion).toBe("http/1.1"); } expect(response.status()).toBe(200); const text = await response.text(); - expect( - text.includes( - '', - ), - ).toBe(true); + expect(text).toContain( + '', + ); expect(consoleMessages.map((message) => message.text())).toEqual([ "[webpack-dev-server] Server started: Hot Module Replacement enabled, Live Reloading enabled, Progress disabled, Overlay enabled.", "[HMR] Waiting for update signal from WDS...", diff --git a/test/e2e/bonjour.test.js b/test/e2e/bonjour.test.js index e0911f14b5..5f2bc90aab 100644 --- a/test/e2e/bonjour.test.js +++ b/test/e2e/bonjour.test.js @@ -1,6 +1,6 @@ "use strict"; -const os = require("os"); +const os = require("node:os"); const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/simple-config/webpack.config"); @@ -29,17 +29,13 @@ describe("bonjour option", () => { let consoleMessages; beforeEach(async () => { - jest.mock("bonjour-service", () => { - return { - Bonjour: jest.fn().mockImplementation(() => { - return { - publish: mockPublish, - unpublishAll: mockUnpublishAll, - destroy: mockDestroy, - }; - }), - }; - }); + jest.mock("bonjour-service", () => ({ + Bonjour: jest.fn().mockImplementation(() => ({ + publish: mockPublish, + unpublishAll: mockUnpublishAll, + destroy: mockDestroy, + })), + })); compiler = webpack(config); @@ -106,17 +102,13 @@ describe("bonjour option", () => { let consoleMessages; beforeEach(async () => { - jest.mock("bonjour-service", () => { - return { - Bonjour: jest.fn().mockImplementation(() => { - return { - publish: mockPublish, - unpublishAll: mockUnpublishAll, - destroy: mockDestroy, - }; - }), - }; - }); + jest.mock("bonjour-service", () => ({ + Bonjour: jest.fn().mockImplementation(() => ({ + publish: mockPublish, + unpublishAll: mockUnpublishAll, + destroy: mockDestroy, + })), + })); compiler = webpack(config); @@ -179,17 +171,13 @@ describe("bonjour option", () => { let consoleMessages; beforeEach(async () => { - jest.mock("bonjour-service", () => { - return { - Bonjour: jest.fn().mockImplementation(() => { - return { - publish: mockPublish, - unpublishAll: mockUnpublishAll, - destroy: mockDestroy, - }; - }), - }; - }); + jest.mock("bonjour-service", () => ({ + Bonjour: jest.fn().mockImplementation(() => ({ + publish: mockPublish, + unpublishAll: mockUnpublishAll, + destroy: mockDestroy, + })), + })); compiler = webpack(config); @@ -262,17 +250,13 @@ describe("bonjour option", () => { let consoleMessages; beforeEach(async () => { - jest.mock("bonjour-service", () => { - return { - Bonjour: jest.fn().mockImplementation(() => { - return { - publish: mockPublish, - unpublishAll: mockUnpublishAll, - destroy: mockDestroy, - }; - }), - }; - }); + jest.mock("bonjour-service", () => ({ + Bonjour: jest.fn().mockImplementation(() => ({ + publish: mockPublish, + unpublishAll: mockUnpublishAll, + destroy: mockDestroy, + })), + })); compiler = webpack(config); diff --git a/test/e2e/built-in-routes.test.js b/test/e2e/built-in-routes.test.js index d5dd08f212..faab99f224 100644 --- a/test/e2e/built-in-routes.test.js +++ b/test/e2e/built-in-routes.test.js @@ -112,7 +112,7 @@ describe("Built in routes", () => { }, ); - expect(response.headers()["content-type"]).not.toEqual("text/html"); + expect(response.headers()["content-type"]).not.toBe("text/html"); expect(response.status()).toMatchSnapshot("response status"); diff --git a/test/e2e/client-reconnect.test.js b/test/e2e/client-reconnect.test.js index 1269743c74..345bb63cf8 100644 --- a/test/e2e/client-reconnect.test.js +++ b/test/e2e/client-reconnect.test.js @@ -125,8 +125,8 @@ describe("client.reconnect option", () => { () => { resolve(); }, - // eslint-disable-next-line no-restricted-properties - 1000 * Math.pow(2, 3), + + 1000 * 2 ** 3, ), ); @@ -190,8 +190,8 @@ describe("client.reconnect option", () => { () => { resolve(); }, - // eslint-disable-next-line no-restricted-properties - 1000 * Math.pow(2, 3), + + 1000 * 2 ** 3, ), ); diff --git a/test/e2e/client.test.js b/test/e2e/client.test.js index bd8b24e4b4..335ca39648 100644 --- a/test/e2e/client.test.js +++ b/test/e2e/client.test.js @@ -200,13 +200,12 @@ describe("client option", () => { let browser; class OverrideServer extends Server { - // eslint-disable-next-line class-methods-use-this getClientEntry() { return require.resolve( "../fixtures/custom-client/CustomClientEntry.js", ); } - // eslint-disable-next-line class-methods-use-this + getClientHotEntry() { return require.resolve( "../fixtures/custom-client/CustomClientHotEntry.js", @@ -304,7 +303,7 @@ describe("client option", () => { ]; describe("passed to server", () => { - clientModes.forEach((data) => { + for (const data of clientModes) { it(`${data.title} ${ data.shouldThrow ? "should throw" : "should not throw" }`, async () => { @@ -334,7 +333,7 @@ describe("client option", () => { await server.stop(); }); - }); + } }); }); }); diff --git a/test/e2e/cross-origin-request.test.js b/test/e2e/cross-origin-request.test.js index 65de9cf3f2..ff8b8959a1 100644 --- a/test/e2e/cross-origin-request.test.js +++ b/test/e2e/cross-origin-request.test.js @@ -22,7 +22,8 @@ describe("cross-origin requests", () => { await server.start(); // Start a separate server for serving the HTML file - const http = require("http"); + const http = require("node:http"); + const htmlServer = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/html" }); res.end(` @@ -77,7 +78,8 @@ describe("cross-origin requests", () => { await server.start(); // Start a separate server for serving the HTML file - const http = require("http"); + const http = require("node:http"); + const htmlServer = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/html" }); res.end(` @@ -129,7 +131,8 @@ describe("cross-origin requests", () => { await server.start(); // Start a separate server for serving the HTML file - const http = require("http"); + const http = require("node:http"); + const htmlServer = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/html" }); res.end(` @@ -181,7 +184,8 @@ describe("cross-origin requests", () => { await server.start(); // Start a separate server for serving the HTML file - const http = require("http"); + const http = require("node:http"); + const htmlServer = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/html" }); res.end(` diff --git a/test/e2e/entry.test.js b/test/e2e/entry.test.js index ff07fbc01a..3917c94a47 100644 --- a/test/e2e/entry.test.js +++ b/test/e2e/entry.test.js @@ -1,6 +1,6 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/client-config/webpack.config"); diff --git a/test/e2e/headers.test.js b/test/e2e/headers.test.js index d176cc7730..efaddab452 100644 --- a/test/e2e/headers.test.js +++ b/test/e2e/headers.test.js @@ -1,7 +1,7 @@ "use strict"; -const webpack = require("webpack"); const request = require("supertest"); +const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/simple-config/webpack.config"); const runBrowser = require("../helpers/run-browser"); @@ -211,9 +211,7 @@ describe("headers option", () => { server = new Server( { - headers: () => { - return { "X-Bar": ["key1=value1", "key2=value2"] }; - }, + headers: () => ({ "X-Bar": ["key1=value1", "key2=value2"] }), port, }, compiler, @@ -450,7 +448,7 @@ describe("headers option", () => { ); expect(pageErrors).toMatchSnapshot("page errors"); - const responseForHead = await req.get(`/`); + const responseForHead = await req.get("/"); expect(responseForHead.headers["x-foo"]).toBe("dev-server headers"); }); diff --git a/test/e2e/history-api-fallback.test.js b/test/e2e/history-api-fallback.test.js index cf8874189d..b6506e85af 100644 --- a/test/e2e/history-api-fallback.test.js +++ b/test/e2e/history-api-fallback.test.js @@ -1,11 +1,11 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const webpack = require("webpack"); const Server = require("../../lib/Server"); -const config = require("../fixtures/historyapifallback-config/webpack.config"); const config2 = require("../fixtures/historyapifallback-2-config/webpack.config"); const config3 = require("../fixtures/historyapifallback-3-config/webpack.config"); +const config = require("../fixtures/historyapifallback-config/webpack.config"); const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map")["history-api-fallback-option"]; @@ -438,7 +438,7 @@ describe("historyApiFallback option", () => { let consoleSpy; beforeEach(async () => { - consoleSpy = jest.spyOn(global.console, "log"); + consoleSpy = jest.spyOn(globalThis.console, "log"); compiler = webpack(config); @@ -514,7 +514,7 @@ describe("historyApiFallback option", () => { let consoleSpy; beforeEach(async () => { - consoleSpy = jest.spyOn(global.console, "log"); + consoleSpy = jest.spyOn(globalThis.console, "log"); compiler = webpack(config); diff --git a/test/e2e/host.test.js b/test/e2e/host.test.js index 227e298b37..c7be637a66 100644 --- a/test/e2e/host.test.js +++ b/test/e2e/host.test.js @@ -1,6 +1,6 @@ "use strict"; -const http = require("http"); +const http = require("node:http"); const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/client-config/webpack.config"); @@ -58,7 +58,7 @@ async function getAddress(host, hostname) { describe("host", () => { const hosts = [ "", - // eslint-disable-next-line no-undefined + undefined, "0.0.0.0", "::", diff --git a/test/e2e/hot-and-live-reload.test.js b/test/e2e/hot-and-live-reload.test.js index c53694e60b..ba2c6ee06a 100644 --- a/test/e2e/hot-and-live-reload.test.js +++ b/test/e2e/hot-and-live-reload.test.js @@ -4,18 +4,18 @@ "use strict"; -const path = require("path"); -const WebSocket = require("ws"); +const path = require("node:path"); +const fs = require("graceful-fs"); const SockJS = require("sockjs-client"); const webpack = require("webpack"); -const fs = require("graceful-fs"); +const WebSocket = require("ws"); const Server = require("../../lib/Server"); -const HTMLGeneratorPlugin = require("../helpers/html-generator-plugin"); +const config = require("../fixtures/client-config/webpack.config"); +const multiCompilerConfig = require("../fixtures/multi-compiler-one-configuration/webpack.config"); const reloadConfig = require("../fixtures/reload-config/webpack.config"); +const HTMLGeneratorPlugin = require("../helpers/html-generator-plugin"); const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map")["hot-and-live-reload"]; -const config = require("../fixtures/client-config/webpack.config"); -const multiCompilerConfig = require("../fixtures/multi-compiler-one-configuration/webpack.config"); const cssFilePath = path.resolve( __dirname, @@ -326,7 +326,7 @@ describe("hot and live reload", () => { fs.unlinkSync(cssFilePath); }); - modes.forEach((mode) => { + for (const mode of modes) { const webSocketServerTitle = mode.options && mode.options.webSocketServer ? mode.options.webSocketServer @@ -368,11 +368,8 @@ describe("hot and live reload", () => { let errored = false; ws.on("error", (error) => { - if (!webSocketServerLaunched && /404/.test(error)) { - errored = true; - } else { - errored = true; - } + errored = + !webSocketServerLaunched && /404/.test(error) ? true : true; ws.close(); }); @@ -439,7 +436,7 @@ describe("hot and live reload", () => { ({ browser } = launched); - const page = launched.page; + const { page } = launched; const consoleMessages = []; const pageErrors = []; @@ -470,12 +467,12 @@ describe("hot and live reload", () => { }); const backgroundColorBefore = await page.evaluate(() => { - const body = document.body; + const { body } = document; return getComputedStyle(body)["background-color"]; }); - expect(backgroundColorBefore).toEqual("rgb(0, 0, 255)"); + expect(backgroundColorBefore).toBe("rgb(0, 0, 255)"); fs.writeFileSync( cssFilePath, @@ -555,21 +552,21 @@ describe("hot and live reload", () => { } const backgroundColorAfter = await page.evaluate(() => { - const body = document.body; + const { body } = document; return getComputedStyle(body)["background-color"]; }); if (!waitHot && !waitLiveReload) { - expect(backgroundColorAfter).toEqual("rgb(0, 0, 255)"); + expect(backgroundColorAfter).toBe("rgb(0, 0, 255)"); } else { - expect(backgroundColorAfter).toEqual("rgb(255, 0, 0)"); + expect(backgroundColorAfter).toBe("rgb(255, 0, 0)"); } expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); }); - }); + } }); // the following cases check to make sure that the HMR @@ -722,13 +719,11 @@ describe("simple config with already added HMR plugin", () => { getInfrastructureLoggerSpy = jest .spyOn(compiler, "getInfrastructureLogger") - .mockImplementation(() => { - return { - warn: loggerWarnSpy, - info: () => {}, - log: () => {}, - }; - }); + .mockImplementation(() => ({ + warn: loggerWarnSpy, + info: () => {}, + log: () => {}, + })); }); afterEach(() => { @@ -742,31 +737,31 @@ describe("simple config with already added HMR plugin", () => { await server.start(); expect(loggerWarnSpy).toHaveBeenCalledWith( - `"hot: true" automatically applies HMR plugin, you don't have to add it manually to your webpack configuration.`, + '"hot: true" automatically applies HMR plugin, you don\'t have to add it manually to your webpack configuration.', ); await server.stop(); }); - it(`should show warning with "hot: true"`, async () => { + it('should show warning with "hot: true"', async () => { server = new Server({ port, hot: true }, compiler); await server.start(); expect(loggerWarnSpy).toHaveBeenCalledWith( - `"hot: true" automatically applies HMR plugin, you don't have to add it manually to your webpack configuration.`, + '"hot: true" automatically applies HMR plugin, you don\'t have to add it manually to your webpack configuration.', ); await server.stop(); }); - it(`should not show warning with "hot: false"`, async () => { + it('should not show warning with "hot: false"', async () => { server = new Server({ port, hot: false }, compiler); await server.start(); expect(loggerWarnSpy).not.toHaveBeenCalledWith( - `"hot: true" automatically applies HMR plugin, you don't have to add it manually to your webpack configuration.`, + '"hot: true" automatically applies HMR plugin, you don\'t have to add it manually to your webpack configuration.', ); await server.stop(); diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js index a29f7acf2e..8607da2053 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -1,11 +1,11 @@ "use strict"; -const os = require("os"); -const net = require("net"); -const path = require("path"); -const http = require("http"); -const webpack = require("webpack"); +const http = require("node:http"); +const net = require("node:net"); +const os = require("node:os"); +const path = require("node:path"); const httpProxy = require("http-proxy"); +const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/client-config/webpack.config"); const runBrowser = require("../helpers/run-browser"); @@ -107,8 +107,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -211,8 +209,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -222,6 +218,7 @@ describe("web socket server URL", () => { }); // TODO un skip after implement new API + // eslint-disable-next-line jest/no-disabled-tests it.skip(`should work with the "ipc" option using "string" value and remove old ("${webSocketServer}")`, async () => { const isWindows = process.platform === "win32"; const localRelative = path.relative(process.cwd(), `${os.tmpdir()}/`); @@ -236,6 +233,7 @@ describe("web socket server URL", () => { reject(error); }); + // eslint-disable-next-line no-promise-executor-return return server.listen(ipc, () => { resolve(); }); @@ -330,8 +328,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); diff --git a/test/e2e/lazy-compilation.test.js b/test/e2e/lazy-compilation.test.js index e3c2db45f9..8bb5390fa5 100644 --- a/test/e2e/lazy-compilation.test.js +++ b/test/e2e/lazy-compilation.test.js @@ -2,14 +2,15 @@ const webpack = require("webpack"); const Server = require("../../lib/Server"); -const lazyCompilationSingleEntryConfig = require("../fixtures/lazy-compilation-single-entry/webpack.config"); const lazyCompilationMultipleEntriesConfig = require("../fixtures/lazy-compilation-multiple-entries/webpack.config"); +const lazyCompilationSingleEntryConfig = require("../fixtures/lazy-compilation-single-entry/webpack.config"); const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map")["lazy-compilation"]; +/* eslint-disable jest/no-disabled-tests */ describe("lazy compilation", () => { // TODO jest freeze due webpack do not close `eventsource`, we should uncomment this after fix it on webpack side - it.skip(`should work with single entry`, async () => { + it.skip("should work with single entry", async () => { const compiler = webpack(lazyCompilationSingleEntryConfig); const server = new Server({ port }, compiler); @@ -44,15 +45,13 @@ describe("lazy compilation", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); } }); - it.skip(`should work with multiple entries`, async () => { + it.skip("should work with multiple entries", async () => { const compiler = webpack(lazyCompilationMultipleEntriesConfig); const server = new Server({ port }, compiler); @@ -102,8 +101,6 @@ describe("lazy compilation", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/e2e/logging.test.js b/test/e2e/logging.test.js index 7a709c1da8..b00d2fa783 100644 --- a/test/e2e/logging.test.js +++ b/test/e2e/logging.test.js @@ -1,11 +1,11 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const fs = require("graceful-fs"); const webpack = require("webpack"); const Server = require("../../lib/Server"); -const HTMLGeneratorPlugin = require("../helpers/html-generator-plugin"); const config = require("../fixtures/client-config/webpack.config"); +const HTMLGeneratorPlugin = require("../helpers/html-generator-plugin"); const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map").logging; @@ -188,8 +188,8 @@ describe("logging", () => { }, ]; - webSocketServers.forEach((webSocketServer) => { - cases.forEach((testCase) => { + for (const webSocketServer of webSocketServers) { + for (const testCase of cases) { it(`${testCase.title} (${ webSocketServer.webSocketServer || "default" })`, async () => { @@ -230,20 +230,18 @@ describe("logging", () => { consoleMessages.map((message) => message .text() - .replace(/\\/g, "/") - .replace( - new RegExp(process.cwd().replace(/\\/g, "/"), "g"), + .replaceAll("\\", "/") + .replaceAll( + new RegExp(process.cwd().replaceAll("\\", "/"), "g"), "", ), ), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); } }); - }); - }); + } + } }); diff --git a/test/e2e/module-federation.test.js b/test/e2e/module-federation.test.js index 3bbf7a9e4a..c544f0d61c 100644 --- a/test/e2e/module-federation.test.js +++ b/test/e2e/module-federation.test.js @@ -1,11 +1,11 @@ "use strict"; -const webpack = require("webpack"); const requireFromString = require("require-from-string"); +const webpack = require("webpack"); const Server = require("../../lib/Server"); const simpleConfig = require("../fixtures/module-federation-config/webpack.config"); -const objectEntryConfig = require("../fixtures/module-federation-config/webpack.object-entry.config"); const multiConfig = require("../fixtures/module-federation-config/webpack.multi.config"); +const objectEntryConfig = require("../fixtures/module-federation-config/webpack.object-entry.config"); const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map")["module-federation"]; const pluginConfig = require("../fixtures/module-federation-config/webpack.plugin"); @@ -59,7 +59,7 @@ describe("Module federation", () => { exports = requireFromString(textContent); }).not.toThrow(); - expect(exports).toEqual("entry2"); + expect(exports).toBe("entry2"); expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( "console messages", @@ -117,7 +117,7 @@ describe("Module federation", () => { exports = requireFromString(textContent); }).not.toThrow(); - expect(exports).toEqual("entry2"); + expect(exports).toBe("entry2"); expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( "console messages", @@ -149,7 +149,7 @@ describe("Module federation", () => { exports = requireFromString(textContent); }).not.toThrow(); - expect(exports).toEqual("entry1"); + expect(exports).toBe("entry1"); expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( "console messages", @@ -207,7 +207,7 @@ describe("Module federation", () => { exports = requireFromString(textContent); }).not.toThrow(); - expect(exports).toEqual("entry2"); + expect(exports).toBe("entry2"); expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( "console messages", diff --git a/test/e2e/multi-compiler.test.js b/test/e2e/multi-compiler.test.js index 6142094f93..73879d5323 100644 --- a/test/e2e/multi-compiler.test.js +++ b/test/e2e/multi-compiler.test.js @@ -1,6 +1,6 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const fs = require("graceful-fs"); const webpack = require("webpack"); const Server = require("../../lib/Server"); @@ -11,7 +11,7 @@ const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map")["multi-compiler"]; describe("multi compiler", () => { - it(`should work with one web target configuration and do nothing`, async () => { + it("should work with one web target configuration and do nothing", async () => { const compiler = webpack(oneWebTargetConfiguration); const devServerOptions = { port, @@ -40,15 +40,13 @@ describe("multi compiler", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); } }); - it(`should work with web target configurations and do nothing`, async () => { + it("should work with web target configurations and do nothing", async () => { const compiler = webpack(twoWebTargetConfiguration); const devServerOptions = { port, @@ -88,15 +86,13 @@ describe("multi compiler", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); } }); - it(`should work with web target configurations when hot and live reloads are enabled, and do hot reload by default when changing own entries`, async () => { + it("should work with web target configurations when hot and live reloads are enabled, and do hot reload by default when changing own entries", async () => { const compiler = webpack(twoWebTargetConfiguration); const devServerOptions = { port, @@ -164,8 +160,6 @@ describe("multi compiler", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -175,7 +169,7 @@ describe("multi compiler", () => { } }); - it(`should work with web target configurations when only hot reload is enabled, and do hot reload when changing own entries`, async () => { + it("should work with web target configurations when only hot reload is enabled, and do hot reload when changing own entries", async () => { const compiler = webpack(twoWebTargetConfiguration); const devServerOptions = { port, @@ -243,8 +237,6 @@ describe("multi compiler", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -254,7 +246,7 @@ describe("multi compiler", () => { } }); - it(`should work with web target configurations when only live reload is enabled, and do live reload when changing own entries`, async () => { + it("should work with web target configurations when only live reload is enabled, and do live reload when changing own entries", async () => { const compiler = webpack(twoWebTargetConfiguration); const devServerOptions = { port, @@ -314,8 +306,6 @@ describe("multi compiler", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -325,7 +315,7 @@ describe("multi compiler", () => { } }); - it(`should work with web target configurations when only live reload is enabled and do live reload when changing other entries`, async () => { + it("should work with web target configurations when only live reload is enabled and do live reload when changing other entries", async () => { const compiler = webpack(twoWebTargetConfiguration); const devServerOptions = { port, @@ -385,8 +375,6 @@ describe("multi compiler", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -433,8 +421,6 @@ describe("multi compiler", () => { await page.goto(`http://localhost:${port}/browser.html`, { waitUntil: "networkidle0", }); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -444,7 +430,7 @@ describe("multi compiler", () => { expect(pageErrors).toMatchSnapshot("page errors"); }); - it(`should work with universal configuration when hot and live reloads are enabled, and do hot reload for browser compiler by default when browser entry changed`, async () => { + it("should work with universal configuration when hot and live reloads are enabled, and do hot reload for browser compiler by default when browser entry changed", async () => { const compiler = webpack(universalConfiguration); const devServerOptions = { port, @@ -513,8 +499,6 @@ describe("multi compiler", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -524,7 +508,7 @@ describe("multi compiler", () => { } }); - it(`should work with universal configuration when only hot reload is enabled, and do hot reload for browser compiler when browser entry changed`, async () => { + it("should work with universal configuration when only hot reload is enabled, and do hot reload for browser compiler when browser entry changed", async () => { const compiler = webpack(universalConfiguration); const devServerOptions = { port, @@ -588,8 +572,6 @@ describe("multi compiler", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -598,7 +580,7 @@ describe("multi compiler", () => { } }); - it(`should work with universal configuration when only live reload is enabled, and do live reload for browser compiler when changing browser and server entries`, async () => { + it("should work with universal configuration when only live reload is enabled, and do live reload for browser compiler when changing browser and server entries", async () => { const compiler = webpack(universalConfiguration); const devServerOptions = { port, @@ -676,8 +658,6 @@ describe("multi compiler", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -687,7 +667,7 @@ describe("multi compiler", () => { } }); - it(`should work with universal configuration when only live reload is enabled, and do live reload for browser compiler when changing server and browser entries`, async () => { + it("should work with universal configuration when only live reload is enabled, and do live reload for browser compiler when changing server and browser entries", async () => { const compiler = webpack(universalConfiguration); const devServerOptions = { port, @@ -765,8 +745,6 @@ describe("multi compiler", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/e2e/options-middleware.test.js b/test/e2e/options-middleware.test.js index 9f8f2cef2f..fcaec60b64 100644 --- a/test/e2e/options-middleware.test.js +++ b/test/e2e/options-middleware.test.js @@ -1,7 +1,7 @@ "use strict"; -const webpack = require("webpack"); const Express = require("express"); +const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/client-config/webpack.config"); const runBrowser = require("../helpers/run-browser"); @@ -84,7 +84,7 @@ describe("handle options-request correctly", () => { await page.evaluate( (url) => - window.fetch(url, { + globalThis.fetch(url, { headers: { "another-header": "1", }, diff --git a/test/e2e/overlay.test.js b/test/e2e/overlay.test.js index 023b9a331a..ef2bf5ac10 100644 --- a/test/e2e/overlay.test.js +++ b/test/e2e/overlay.test.js @@ -1,12 +1,12 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const fs = require("graceful-fs"); -const webpack = require("webpack"); const waitForExpect = require("wait-for-expect"); +const webpack = require("webpack"); const Server = require("../../lib/Server"); -const config = require("../fixtures/overlay-config/webpack.config"); const trustedTypesConfig = require("../fixtures/overlay-config/trusted-types.webpack.config"); +const config = require("../fixtures/overlay-config/webpack.config"); const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map").overlay; @@ -118,9 +118,7 @@ describe("overlay", () => { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; + ).toMatchSnapshot("overlay html"); } finally { await browser.close(); await server.stop(); @@ -168,8 +166,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -221,8 +217,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -271,9 +265,7 @@ describe("overlay", () => { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; + ).toMatchSnapshot("overlay html"); } finally { await browser.close(); await server.stop(); @@ -322,8 +314,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -349,7 +339,7 @@ describe("overlay", () => { let pageHtml = await page.evaluate(() => document.body.outerHTML); let overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); expect( await prettier.format(pageHtml, { parser: "html", @@ -397,15 +387,13 @@ describe("overlay", () => { pageHtml = await page.evaluate(() => document.body.outerHTML); overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); expect( await prettier.format(pageHtml, { parser: "html", plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("page html after fix error"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -431,7 +419,7 @@ describe("overlay", () => { let pageHtml = await page.evaluate(() => document.body.outerHTML); let overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); expect( await prettier.format(pageHtml, { parser: "html", @@ -505,15 +493,13 @@ describe("overlay", () => { pageHtml = await page.evaluate(() => document.body.outerHTML); overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); expect( await prettier.format(pageHtml, { parser: "html", plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("page html after fix error"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -539,7 +525,7 @@ describe("overlay", () => { let pageHtml = await page.evaluate(() => document.body.outerHTML); let overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); expect( await prettier.format(pageHtml, { parser: "html", @@ -593,7 +579,7 @@ describe("overlay", () => { pageHtml = await page.evaluate(() => document.body.outerHTML); overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); expect( await prettier.format(pageHtml, { parser: "html", @@ -652,8 +638,6 @@ describe("overlay", () => { }); fs.writeFileSync(pathToFile, originalCode); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -688,15 +672,13 @@ describe("overlay", () => { const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); expect( await prettier.format(pageHtml, { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("page html"); - } catch (error) { - throw error; + ).toMatchSnapshot("page html"); } finally { await browser.close(); await server.stop(); @@ -733,15 +715,13 @@ describe("overlay", () => { const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); expect( await prettier.format(pageHtml, { parser: "html", plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("page html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -783,7 +763,7 @@ describe("overlay", () => { const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); } catch (error) { throw error; } finally { @@ -840,8 +820,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -891,9 +869,7 @@ describe("overlay", () => { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; + ).toMatchSnapshot("overlay html"); } finally { await browser.close(); await server.stop(); @@ -946,8 +922,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1000,8 +974,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1036,15 +1008,13 @@ describe("overlay", () => { const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); expect( await prettier.format(pageHtml, { parser: "html", plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("page html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1081,15 +1051,13 @@ describe("overlay", () => { const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); expect( await prettier.format(pageHtml, { parser: "html", plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("page html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1132,7 +1100,7 @@ describe("overlay", () => { const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); } catch (error) { throw error; } finally { @@ -1189,8 +1157,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1241,8 +1207,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1305,9 +1269,7 @@ describe("overlay", () => { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; + ).toMatchSnapshot("overlay html"); } finally { await browser.close(); await server.stop(); @@ -1381,8 +1343,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1418,15 +1378,13 @@ describe("overlay", () => { const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); expect( await prettier.format(pageHtml, { parser: "html", plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("page html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1479,8 +1437,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1533,8 +1489,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1609,8 +1563,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("page html"); - } catch (error) { - throw error; } finally { await browser.close(); } @@ -1670,9 +1622,7 @@ describe("overlay", () => { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; + ).toMatchSnapshot("overlay html"); } finally { await browser.close(); await server.stop(); @@ -1782,8 +1732,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1825,7 +1773,7 @@ describe("overlay", () => { const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); + expect(overlayHandle).toBeNull(); } catch (error) { throw error; } finally { @@ -1876,8 +1824,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1921,9 +1867,7 @@ describe("overlay", () => { const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); - expect(overlayHandle).toBe(null); - } catch (error) { - throw error; + expect(overlayHandle).toBeNull(); } finally { await browser.close(); await server.stop(); @@ -1989,8 +1933,6 @@ describe("overlay", () => { }, ), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/e2e/port.test.js b/test/e2e/port.test.js index 9939a870aa..b7824a49e9 100644 --- a/test/e2e/port.test.js +++ b/test/e2e/port.test.js @@ -4,12 +4,12 @@ const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/client-config/webpack.config"); const runBrowser = require("../helpers/run-browser"); -const port = require("../ports-map").port; +const { port } = require("../ports-map"); describe("port", () => { const ports = [ "", - // eslint-disable-next-line no-undefined + undefined, "auto", port, @@ -52,14 +52,10 @@ describe("port", () => { } if (testedPort === "-1" || testedPort === "99999") { - const errorMessageRegExp = new RegExp( - `options.port should be >= 0 and < 65536`, - ); + const errorMessageRegExp = /options.port should be >= 0 and < 65536/; try { expect(errored.message).toMatch(errorMessageRegExp); - } catch (error) { - throw error; } finally { await server.stop(); } @@ -97,8 +93,6 @@ describe("port", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/e2e/progress.test.js b/test/e2e/progress.test.js index 2aedf72bbf..3f922d98c0 100644 --- a/test/e2e/progress.test.js +++ b/test/e2e/progress.test.js @@ -1,6 +1,6 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const fs = require("graceful-fs"); const webpack = require("webpack"); const Server = require("../../lib/Server"); @@ -66,8 +66,6 @@ describe("progress", () => { } }, 100); }); - } catch (error) { - throw error; } finally { await browser.close(); } @@ -78,9 +76,7 @@ describe("progress", () => { ), ); - expect(progressConsoleMessage.length > 0).toBe(true); - } catch (error) { - throw error; + expect(progressConsoleMessage.length).toBeGreaterThan(0); } finally { fs.unlinkSync(cssFilePath); diff --git a/test/e2e/range-header.test.js b/test/e2e/range-header.test.js index 298d472be7..19701cbedb 100644 --- a/test/e2e/range-header.test.js +++ b/test/e2e/range-header.test.js @@ -43,7 +43,7 @@ describe("'Range' header", () => { expect(responseRange.headers["content-length"]).toBe("500"); expect(responseRange.headers["content-range"]).toMatch(/^bytes 0-499\//); expect(responseRange.text).toBe(responseContent.slice(0, 500)); - expect(responseRange.text.length).toBe(500); + expect(responseRange.text).toHaveLength(500); }); it('should work with "Range" header using "HEAD" method', async () => { @@ -106,6 +106,6 @@ describe("'Range' header", () => { "application/javascript; charset=utf-8", ); expect(responseRange.text).toBe(responseContent); - expect(responseRange.text.length).toBe(responseContent.length); + expect(responseRange.text).toHaveLength(responseContent.length); }); }); diff --git a/test/e2e/server-and-client-transport.test.js b/test/e2e/server-and-client-transport.test.js index e00e0a272a..763a4be353 100644 --- a/test/e2e/server-and-client-transport.test.js +++ b/test/e2e/server-and-client-transport.test.js @@ -3,10 +3,10 @@ const webpack = require("webpack"); const Server = require("../../lib/Server"); const WebsocketServer = require("../../lib/servers/WebsocketServer"); +const customConfig = require("../fixtures/provide-plugin-custom/webpack.config"); const defaultConfig = require("../fixtures/provide-plugin-default/webpack.config"); const sockjsConfig = require("../fixtures/provide-plugin-sockjs-config/webpack.config"); const wsConfig = require("../fixtures/provide-plugin-ws-config/webpack.config"); -const customConfig = require("../fixtures/provide-plugin-custom/webpack.config"); const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map")["server-and-client-transport"]; @@ -34,15 +34,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -73,15 +71,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -114,15 +110,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -153,15 +147,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -194,15 +186,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -236,15 +226,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -280,15 +268,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -322,15 +308,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -366,15 +350,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -428,15 +410,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -469,15 +449,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -511,15 +489,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -553,15 +529,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -597,15 +571,13 @@ describe("server and client transport", () => { }); const isCorrectTransport = await page.evaluate( - () => window.injectedClient === window.expectedClient, + () => globalThis.injectedClient === globalThis.expectedClient, ); expect(isCorrectTransport).toBe(true); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/e2e/server.test.js b/test/e2e/server.test.js index f17f0e5627..457e4c8558 100644 --- a/test/e2e/server.test.js +++ b/test/e2e/server.test.js @@ -1,16 +1,16 @@ "use strict"; -const https = require("https"); -const path = require("path"); +const https = require("node:https"); +const path = require("node:path"); const fs = require("graceful-fs"); const request = require("supertest"); const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/static-config/webpack.config"); -const runBrowser = require("../helpers/run-browser"); const { skipTestOnWindows } = require("../helpers/conditional-test"); const customHTTP = require("../helpers/custom-http"); const normalizeOptions = require("../helpers/normalize-options"); +const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map")["server-option"]; const httpsCertificateDirectory = path.resolve( @@ -80,7 +80,7 @@ describe("server option", () => { () => performance.getEntries()[0].nextHopProtocol, ); - expect(HTTPVersion).not.toEqual("h2"); + expect(HTTPVersion).not.toBe("h2"); expect(response.status()).toMatchSnapshot("response status"); @@ -140,7 +140,7 @@ describe("server option", () => { () => performance.getEntries()[0].nextHopProtocol, ); - expect(HTTPVersion).not.toEqual("h2"); + expect(HTTPVersion).not.toBe("h2"); expect(response.status()).toMatchSnapshot("response status"); @@ -200,7 +200,7 @@ describe("server option", () => { () => performance.getEntries()[0].nextHopProtocol, ); - expect(HTTPVersion).not.toEqual("h2"); + expect(HTTPVersion).not.toBe("h2"); expect(response.status()).toMatchSnapshot("response status"); @@ -260,7 +260,7 @@ describe("server option", () => { () => performance.getEntries()[0].nextHopProtocol, ); - expect(HTTPVersion).toEqual("h2"); + expect(HTTPVersion).toBe("h2"); expect(response.status()).toBe(200); expect((await response.text()).trim()).toBe("Heyo."); expect(consoleMessages).toHaveLength(0); @@ -851,7 +851,7 @@ describe("server option", () => { waitUntil: "networkidle0", }); - expect(response.status()).toEqual(200); + expect(response.status()).toBe(200); expect(await response.text()).toContain("Heyo"); expect(consoleMessages.map((message) => message.text())).toEqual([]); expect(pageErrors).toEqual([]); @@ -1346,7 +1346,7 @@ describe("server option", () => { const options = normalizeOptions(createServerSpy.mock.calls[0][0]); - expect(HTTPVersion).toEqual("h2"); + expect(HTTPVersion).toBe("h2"); expect(options.spdy).toEqual({ protocols: ["h2", "http/1.1"] }); expect(response.status()).toBe(200); expect((await response.text()).trim()).toBe("Heyo."); @@ -1418,7 +1418,7 @@ describe("server option", () => { () => performance.getEntries()[0].nextHopProtocol, ); - expect(HTTPVersion).toEqual("http/1.1"); + expect(HTTPVersion).toBe("http/1.1"); expect( normalizeOptions(createServerSpy.mock.calls[0][0]), ).toMatchSnapshot("http options"); diff --git a/test/e2e/setup-exit-signals.test.js b/test/e2e/setup-exit-signals.test.js index 0de9236d34..8b8de09674 100644 --- a/test/e2e/setup-exit-signals.test.js +++ b/test/e2e/setup-exit-signals.test.js @@ -59,9 +59,9 @@ describe("setupExitSignals option", () => { afterEach(async () => { exitSpy.mockReset(); stdinResumeSpy.mockReset(); - signals.forEach((signal) => { + for (const signal of signals) { process.removeAllListeners(signal); - }); + } process.stdin.removeAllListeners("end"); await browser.close(); await server.stop(); @@ -87,10 +87,10 @@ describe("setupExitSignals option", () => { await new Promise((resolve) => { const interval = setInterval(() => { if (doExit) { - expect(stopCallbackSpy.mock.calls.length).toEqual(1); + expect(stopCallbackSpy.mock.calls).toHaveLength(1); if (server.compiler.close) { - expect(closeCallbackSpy.mock.calls.length).toEqual(1); + expect(closeCallbackSpy.mock.calls).toHaveLength(1); } clearInterval(interval); diff --git a/test/e2e/static-directory.test.js b/test/e2e/static-directory.test.js index 982aca59a3..415026ebe0 100644 --- a/test/e2e/static-directory.test.js +++ b/test/e2e/static-directory.test.js @@ -1,13 +1,13 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const fs = require("graceful-fs"); const webpack = require("webpack"); const Server = require("../../lib/Server"); -const testServer = require("../helpers/test-server"); const config = require("../fixtures/static-config/webpack.config"); -const port = require("../ports-map")["static-directory-option"]; const runBrowser = require("../helpers/run-browser"); +const testServer = require("../helpers/test-server"); +const port = require("../ports-map")["static-directory-option"]; const staticDirectory = path.resolve(__dirname, "../fixtures/static-config"); const publicDirectory = path.resolve(staticDirectory, "public"); @@ -100,7 +100,7 @@ describe("static.directory option", () => { expect(pageErrors).toMatchSnapshot("page errors"); }); - it("Watches folder recursively", (done) => { + it("watches folder recursively", (done) => { // chokidar emitted a change, // meaning it watched the file correctly server.staticWatchers[0].on("change", () => { @@ -113,7 +113,7 @@ describe("static.directory option", () => { }, 1000); }); - it("Watches node_modules", (done) => { + it("watches node_modules", (done) => { const filePath = path.join(publicDirectory, "node_modules", "index.html"); fs.writeFileSync(filePath, "foo", "utf8"); @@ -483,7 +483,7 @@ describe("static.directory option", () => { }); }); - it("Should throw exception (external url)", (done) => { + it("should throw exception (external url)", (done) => { expect.assertions(1); server = testServer.start( @@ -501,14 +501,14 @@ describe("static.directory option", () => { ); }); - it("Should not throw exception (local path with lower case first character)", (done) => { + it("should not throw exception (local path with lower case first character)", (done) => { testServer.start( config, { static: { directory: publicDirectory.charAt(0).toLowerCase() + - publicDirectory.substring(1), + publicDirectory.slice(1), watch: true, }, port, @@ -517,7 +517,7 @@ describe("static.directory option", () => { ); }); - it("Should not throw exception (local path with lower case first character & has '-')", (done) => { + it("should not throw exception (local path with lower case first character & has '-')", (done) => { testServer.start( config, { @@ -531,7 +531,7 @@ describe("static.directory option", () => { ); }); - it("Should not throw exception (local path with upper case first character & has '-')", (done) => { + it("should not throw exception (local path with upper case first character & has '-')", (done) => { testServer.start( config, { @@ -545,7 +545,7 @@ describe("static.directory option", () => { ); }); - it("Should throw exception (array with absolute url)", (done) => { + it("should throw exception (array with absolute url)", (done) => { server = testServer.start( config, { @@ -578,7 +578,6 @@ describe("static.directory option", () => { server = new Server( { - // eslint-disable-next-line no-undefined static: undefined, port, }, diff --git a/test/e2e/static-public-path.test.js b/test/e2e/static-public-path.test.js index 6818345f73..8af9cf0e58 100644 --- a/test/e2e/static-public-path.test.js +++ b/test/e2e/static-public-path.test.js @@ -1,11 +1,11 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/static-config/webpack.config"); -const port = require("../ports-map")["static-public-path-option"]; const runBrowser = require("../helpers/run-browser"); +const port = require("../ports-map")["static-public-path-option"]; const staticDirectory = path.resolve(__dirname, "../fixtures/static-config"); const publicDirectory = path.resolve(staticDirectory, "public"); diff --git a/test/e2e/stats.test.js b/test/e2e/stats.test.js index 1d90ef6915..297c31a321 100644 --- a/test/e2e/stats.test.js +++ b/test/e2e/stats.test.js @@ -7,7 +7,7 @@ const HTMLGeneratorPlugin = require("../helpers/html-generator-plugin"); const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map").stats; -global.console.log = jest.fn(); +jest.spyOn(globalThis.console, "log").mockImplementation(); describe("stats", () => { const cases = [ @@ -24,7 +24,6 @@ describe("stats", () => { { title: 'should work using "undefined" value for the "stats" option', webpackOptions: { - // eslint-disable-next-line no-undefined stats: undefined, }, }, @@ -55,7 +54,7 @@ describe("stats", () => { webpackOptions: { stats: { colors: { - green: "\u001b[32m", + green: "\u001B[32m", }, }, }, @@ -108,7 +107,7 @@ describe("stats", () => { }); } - cases.forEach((testCase) => { + for (const testCase of cases) { it(testCase.title, async () => { const compiler = webpack({ ...config, ...testCase.webpackOptions }); const devServerOptions = { @@ -134,12 +133,10 @@ describe("stats", () => { expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); } }); - }); + } }); diff --git a/test/e2e/target.test.js b/test/e2e/target.test.js index 940966fee7..32f9a5aaef 100644 --- a/test/e2e/target.test.js +++ b/test/e2e/target.test.js @@ -1,6 +1,6 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/client-config/webpack.config"); @@ -84,8 +84,6 @@ describe("target", () => { } else { expect(pageErrors).toMatchSnapshot("page errors"); } - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -125,8 +123,6 @@ describe("target", () => { ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -176,8 +172,6 @@ describe("target", () => { ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/e2e/watch-files.test.js b/test/e2e/watch-files.test.js index 732e1077e3..c3785fbbec 100644 --- a/test/e2e/watch-files.test.js +++ b/test/e2e/watch-files.test.js @@ -1,6 +1,6 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const chokidar = require("chokidar"); const fs = require("graceful-fs"); const webpack = require("webpack"); @@ -240,7 +240,7 @@ describe("watchFiles option", () => { beforeEach(async () => { try { fs.unlinkSync(nonExistFile); - } catch (error) { + } catch { // ignore } @@ -599,7 +599,7 @@ describe("watchFiles option", () => { }, ]; - optionCases.forEach((optionCase) => { + for (const optionCase of optionCases) { describe(JSON.stringify(optionCase), () => { let compiler; let server; @@ -677,6 +677,6 @@ describe("watchFiles option", () => { }); }); }); - }); + } }); }); diff --git a/test/e2e/web-socket-communication.test.js b/test/e2e/web-socket-communication.test.js index 21731cf88b..8afb7ac0e5 100644 --- a/test/e2e/web-socket-communication.test.js +++ b/test/e2e/web-socket-communication.test.js @@ -13,7 +13,7 @@ jest.setTimeout(60000); describe("web socket communication", () => { const webSocketServers = ["ws", "sockjs"]; - webSocketServers.forEach((websocketServer) => { + for (const websocketServer of webSocketServers) { it(`should work and close web socket client connection when web socket server closed ("${websocketServer}")`, async () => { WebsocketServer.heartbeatInterval = 100; @@ -59,8 +59,6 @@ describe("web socket communication", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); } @@ -104,13 +102,11 @@ describe("web socket communication", () => { }, 200); }); - expect(server.webSocketServer.clients.length).toBe(0); + expect(server.webSocketServer.clients).toHaveLength(0); expect( consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await server.stop(); } @@ -157,16 +153,14 @@ describe("web socket communication", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); } }); - }); + } - it(`should work and do heartbeat using ("ws" web socket server)`, async () => { + it('should work and do heartbeat using ("ws" web socket server)', async () => { WebsocketServer.heartbeatInterval = 100; const compiler = webpack(config); diff --git a/test/e2e/web-socket-server-url.test.js b/test/e2e/web-socket-server-url.test.js index c781472082..0f33a7a001 100644 --- a/test/e2e/web-socket-server-url.test.js +++ b/test/e2e/web-socket-server-url.test.js @@ -1,8 +1,8 @@ "use strict"; const express = require("express"); -const webpack = require("webpack"); const { createProxyMiddleware } = require("http-proxy-middleware"); +const webpack = require("webpack"); const Server = require("../../lib/Server"); const config = require("../fixtures/client-config/webpack.config"); const runBrowser = require("../helpers/run-browser"); @@ -94,7 +94,7 @@ describe("web socket server URL", () => { await page.goto(`http://${proxyHost}:${proxyPort}/`, { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://${devServerHost}:${devServerPort}/ws`, @@ -103,8 +103,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); await browser.close(); @@ -192,7 +190,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://${devServerHost}:${devServerPort}/ws`, @@ -201,8 +199,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); await browser.close(); @@ -294,7 +290,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://${devServerHost}:${devServerPort}/ws`, @@ -303,8 +299,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -397,7 +391,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://${resolvedHost}:${resolvedPort}/ws`, @@ -406,8 +400,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -477,7 +469,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://localhost:${port1}/ws`, @@ -486,8 +478,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -553,7 +543,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://localhost:${port1}/ws`, @@ -562,8 +552,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -629,7 +617,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://localhost:${port1}/ws`, @@ -638,8 +626,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -705,7 +691,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/ws`, @@ -714,8 +700,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -780,7 +764,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/ws`, @@ -789,8 +773,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -856,7 +838,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/ws`, @@ -865,8 +847,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -932,7 +912,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/ws`, @@ -941,8 +921,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1015,7 +993,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( webSocketServer === "sockjs" @@ -1026,8 +1004,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1092,7 +1068,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/ws`, @@ -1101,8 +1077,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1168,7 +1142,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/ws`, @@ -1177,8 +1151,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1239,7 +1211,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/ws`, @@ -1248,8 +1220,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1314,7 +1284,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://zenitsu@127.0.0.1:${port1}/ws`, @@ -1323,8 +1293,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1393,7 +1361,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( // "sockjs" has bug with parsing URL @@ -1405,8 +1373,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1473,7 +1439,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://zenitsu:chuntaro@127.0.0.1:${port1}/ws`, @@ -1482,8 +1448,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1549,7 +1513,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/custom-ws/foo/bar`, @@ -1558,8 +1522,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1626,7 +1588,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( webSocketServer === "ws" @@ -1637,8 +1599,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1709,7 +1669,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/custom-ws/foo/bar`, @@ -1718,8 +1678,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1790,7 +1748,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/custom-ws`, @@ -1799,8 +1757,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1871,7 +1827,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/custom-ws/`, @@ -1880,8 +1836,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1953,7 +1907,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( webSocketServer === "ws" @@ -1964,8 +1918,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -2038,7 +1990,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/custom-ws`, @@ -2047,8 +1999,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -2108,7 +2058,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://${hostname}:${port1}/ws`, @@ -2117,8 +2067,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -2179,7 +2127,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://${hostname}:${port1}/ws`, @@ -2188,8 +2136,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -2258,8 +2204,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -2320,7 +2264,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; if (webSocketServer === "ws") { expect(webSocketRequest.url).toContain( @@ -2336,8 +2280,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -2402,8 +2344,9 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; + /* eslint-disable jest/no-standalone-expect */ if (webSocketServer === "ws") { expect(webSocketRequest.url).toContain( `wss://${hostname}:${port1}/ws`, @@ -2420,8 +2363,7 @@ describe("web socket server URL", () => { "Hey.", ]); expect(pageErrors).toHaveLength(0); - } catch (error) { - throw error; + /* eslint-enable jest/no-standalone-expect */ } finally { await browser.close(); await server.stop(); @@ -2487,7 +2429,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${resolvedFreePort}/ws`, @@ -2496,8 +2438,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -2568,7 +2508,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/ws`, @@ -2577,8 +2517,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -2642,7 +2580,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://127.0.0.1:${port1}/ws`, @@ -2651,8 +2589,6 @@ describe("web socket server URL", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -2700,8 +2636,6 @@ describe("web socket server URL", () => { pageError.message.split("\n")[0].replace("SyntaxError: ", ""), ), ).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -2737,7 +2671,7 @@ describe("web socket server URL", () => { if (!isDisconnected) { isDisconnected = /Disconnected!/.test(text); - consoleMessages.push(text.replace(/:[\d]+/g, ":")); + consoleMessages.push(text.replaceAll(/:[\d]+/g, ":")); } }) .on("pageerror", (error) => { @@ -2764,8 +2698,6 @@ describe("web socket server URL", () => { expect( pageErrors.map((pageError) => pageError.message.split("\n")[0]), ).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/e2e/web-socket-server.test.js b/test/e2e/web-socket-server.test.js index b3ffde1fb1..b611040e2e 100644 --- a/test/e2e/web-socket-server.test.js +++ b/test/e2e/web-socket-server.test.js @@ -58,8 +58,6 @@ describe("web socket server", () => { "console messages", ); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/helpers/ExitOnDonePlugin.js b/test/helpers/ExitOnDonePlugin.js index 9db636139e..656b58579a 100644 --- a/test/helpers/ExitOnDonePlugin.js +++ b/test/helpers/ExitOnDonePlugin.js @@ -1,7 +1,6 @@ "use strict"; module.exports = class ExitOnDonePlugin { - // eslint-disable-next-line class-methods-use-this apply(compiler) { compiler.hooks.afterDone.tap("webpack-dev-server", (stats) => { let exitCode = 0; @@ -11,6 +10,7 @@ module.exports = class ExitOnDonePlugin { } setImmediate(() => { + // eslint-disable-next-line n/no-process-exit process.exit(exitCode); }); }); diff --git a/test/helpers/custom-http.js b/test/helpers/custom-http.js index 0678c55d9a..29046c9bc3 100644 --- a/test/helpers/custom-http.js +++ b/test/helpers/custom-http.js @@ -1,5 +1,5 @@ "use strict"; -const customHTTP = require("http"); +const customHTTP = require("node:http"); module.exports = customHTTP; diff --git a/test/helpers/html-generator-plugin.js b/test/helpers/html-generator-plugin.js index 0c9fa99202..261d16e592 100644 --- a/test/helpers/html-generator-plugin.js +++ b/test/helpers/html-generator-plugin.js @@ -42,7 +42,6 @@ const HTMLContentForTest = ` `; module.exports = class HTMLGeneratorPlugin { - // eslint-disable-next-line class-methods-use-this apply(compiler) { const pluginName = "html-generator-plugin"; @@ -67,6 +66,7 @@ module.exports = class HTMLGeneratorPlugin { if (assetName !== "main.js") { const assetSource = new RawSource( + // eslint-disable-next-line new-cap HTMLContentForAssets(assetName), ); compilation.emitAsset( diff --git a/test/helpers/normalize-options.js b/test/helpers/normalize-options.js index 64814dc412..750497322f 100644 --- a/test/helpers/normalize-options.js +++ b/test/helpers/normalize-options.js @@ -1,9 +1,11 @@ "use strict"; +/** + * @param options + */ function normalizeOptions(options) { const normalizedOptions = {}; - // eslint-disable-next-line guard-for-in for (const propertyName in options) { let value = options[propertyName]; diff --git a/test/helpers/run-browser.js b/test/helpers/run-browser.js index 90d0c9a10a..85207539aa 100644 --- a/test/helpers/run-browser.js +++ b/test/helpers/run-browser.js @@ -4,47 +4,12 @@ const puppeteer = require("puppeteer"); const { puppeteerArgs } = require("./puppeteer-constants"); /** - * @typedef {Object} RunBrowserResult + * @typedef {object} RunBrowserResult * @property {import('puppeteer').Page} page * @property {import('puppeteer').Browser} browser */ -/** - * @param {Parameters[0]} config - * @returns {Promise} - */ -function runBrowser(config) { - return new Promise((resolve, reject) => { - /** - * @type {import('puppeteer').Page} - */ - let page; - /** - * @type {import('puppeteer').Browser} - */ - let browser; - - puppeteer - .launch({ - headless: "new", - // because of invalid localhost certificate - acceptInsecureCerts: true, - // args come from: https://github.com/alixaxel/chrome-aws-lambda/blob/master/source/index.js - args: puppeteerArgs, - }) - .then((launchedBrowser) => { - browser = launchedBrowser; - - return runPage(launchedBrowser, config); - }) - .then((newPage) => { - page = newPage; - resolve({ page, browser }); - }) - .catch(reject); - }); -} function runPage(browser, config) { /** @@ -90,5 +55,42 @@ function runPage(browser, config) { }); } +/** + * @param {Parameters[0]} config + * @returns {Promise} + */ +function runBrowser(config) { + return new Promise((resolve, reject) => { + /** + * @type {import('puppeteer').Page} + */ + let page; + /** + * @type {import('puppeteer').Browser} + */ + let browser; + + puppeteer + .launch({ + headless: "new", + // because of invalid localhost certificate + acceptInsecureCerts: true, + // args come from: https://github.com/alixaxel/chrome-aws-lambda/blob/master/source/index.js + args: puppeteerArgs, + }) + .then((launchedBrowser) => { + browser = launchedBrowser; + + return runPage(launchedBrowser, config); + }) + .then((newPage) => { + page = newPage; + + resolve({ page, browser }); + }) + .catch(reject); + }); +} + module.exports = runBrowser; module.exports.runPage = runPage; diff --git a/test/helpers/session-subscribe.js b/test/helpers/session-subscribe.js index 34e0a41902..88e71864b5 100644 --- a/test/helpers/session-subscribe.js +++ b/test/helpers/session-subscribe.js @@ -1,8 +1,8 @@ "use strict"; module.exports = async function sessionSubscribe(session) { - session.on("sessionattached", (s) => { - sessionSubscribe(s); + session.on("sessionattached", (attachedSession) => { + sessionSubscribe(attachedSession); }); session.send("Network.enable"); session.send("Runtime.runIfWaitingForDebugger"); diff --git a/test/helpers/snapshotResolver.js b/test/helpers/snapshotResolver.js index e9622480d6..cd4aa21bc0 100644 --- a/test/helpers/snapshotResolver.js +++ b/test/helpers/snapshotResolver.js @@ -1,6 +1,6 @@ "use strict"; -const path = require("path"); +const path = require("node:path"); const webpack = require("webpack"); const [webpackVersion] = webpack.version; diff --git a/test/helpers/test-bin.js b/test/helpers/test-bin.js index 0766445bf6..18cc89d03b 100644 --- a/test/helpers/test-bin.js +++ b/test/helpers/test-bin.js @@ -1,10 +1,10 @@ "use strict"; -const os = require("os"); -const path = require("path"); +const os = require("node:os"); +const path = require("node:path"); const execa = require("execa"); -const stripAnsi = require("strip-ansi-v6"); const { Writable } = require("readable-stream"); +const stripAnsi = require("strip-ansi-v6"); const webpackDevServerPath = path.resolve( __dirname, @@ -123,27 +123,27 @@ const ipV6 = ` (?::(?:(?::${ipV6Seg}){0,5}:${ipV4}|(?::${ipV6Seg}){1,7}|:)) // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::1.2.3.4 )(?:%[0-9a-zA-Z]{1,})? // %eth0 %1 ` - .replace(/\s*\/\/.*$/gm, "") - .replace(/\n/g, "") + .replaceAll(/\s*\/\/.*$/gm, "") + .replaceAll("\n", "") .trim(); const normalizeStderr = (stderr, options = {}) => { let normalizedStderr = stripAnsi(stderr); normalizedStderr = normalizedStderr - .replace(/\\/g, "/") - .replace(new RegExp(process.cwd().replace(/\\/g, "/"), "g"), "") - .replace(new RegExp(os.tmpdir().replace(/\\/g, "/"), "g"), "") - .replace(new RegExp("\\\\.\\pipe".replace(/\\/g, "/"), "g"), "") - .replace(new RegExp(ipV4, "g"), "") - .replace(new RegExp(ipV6, "g"), ""); + .replaceAll("\\", "/") + .replaceAll(new RegExp(process.cwd().replaceAll("\\", "/"), "g"), "") + .replaceAll(new RegExp(os.tmpdir().replaceAll("\\", "/"), "g"), "") + .replaceAll(new RegExp("\\\\.\\pipe".replaceAll("\\", "/"), "g"), "") + .replaceAll(new RegExp(ipV4, "g"), "") + .replaceAll(new RegExp(ipV6, "g"), ""); // normalize node warnings - normalizedStderr = normalizedStderr.replace( + normalizedStderr = normalizedStderr.replaceAll( /.*DeprecationWarning.*(\n)*/gm, "", ); - normalizedStderr = normalizedStderr.replace( + normalizedStderr = normalizedStderr.replaceAll( /.*Use `node --trace-deprecation ...` to show where the warning was created.*(\n)*/gm, "", ); @@ -153,7 +153,7 @@ const normalizeStderr = (stderr, options = {}) => { (item) => !/.+wait until bundle finished.*(\n)?/g.test(item), ); normalizedStderr = normalizedStderr.join("\n"); - normalizedStderr = normalizedStderr.replace(/:[0-9]+\//g, ":/"); + normalizedStderr = normalizedStderr.replaceAll(/:[0-9]+\//g, ":/"); if (options.https) { // We have deprecation warning on windows in some cases diff --git a/test/helpers/test-server.js b/test/helpers/test-server.js index 98272e3fa3..7e9468f333 100644 --- a/test/helpers/test-server.js +++ b/test/helpers/test-server.js @@ -7,6 +7,7 @@ let server; // start server, returning the full setup of the server // (both the server and the compiler) + function startFullSetup(config, options, done) { // disable watching by default for tests if (typeof options.static === "undefined") { @@ -36,6 +37,11 @@ function startFullSetup(config, options, done) { }; } +/** + * @param config + * @param options + * @param done + */ function startAwaitingCompilationFullSetup(config, options, done) { let readyCount = 0; @@ -64,10 +70,20 @@ function startAwaitingCompilationFullSetup(config, options, done) { return fullSetup; } +/** + * @param config + * @param options + * @param done + */ function startAwaitingCompilation(config, options, done) { return startAwaitingCompilationFullSetup(config, options, done).server; } +/** + * @param config + * @param options + * @param done + */ function start(config, options, done) { // I suspect that almost all tests need to wait for compilation to // finish, because not doing so leaves open handles for jest, @@ -78,6 +94,9 @@ function start(config, options, done) { return startAwaitingCompilation(config, options, done); } +/** + * @param done + */ function close(done) { if (server) { server.stopCallback(() => { @@ -90,6 +109,6 @@ function close(done) { } module.exports = { - start, close, + start, }; diff --git a/test/helpers/trusted-types-html-generator-plugin.js b/test/helpers/trusted-types-html-generator-plugin.js index 53a5bd2f65..6d023305db 100644 --- a/test/helpers/trusted-types-html-generator-plugin.js +++ b/test/helpers/trusted-types-html-generator-plugin.js @@ -36,7 +36,6 @@ const HTMLContentForTest = ` `; module.exports = class HTMLGeneratorPlugin { - // eslint-disable-next-line class-methods-use-this apply(compiler) { const pluginName = "html-generator-plugin"; diff --git a/test/normalize-options.test.js b/test/normalize-options.test.js index e4c97d4bb3..b3ae68c021 100644 --- a/test/normalize-options.test.js +++ b/test/normalize-options.test.js @@ -1,7 +1,7 @@ "use strict"; -const webpack = require("webpack"); const { klona } = require("klona/full"); +const webpack = require("webpack"); const Server = require("../lib/Server"); const port = require("./ports-map")["normalize-option"]; @@ -579,7 +579,7 @@ describe("normalize options", () => { }, ]; - cases.forEach((item) => { + for (const item of cases) { it(item.title, async () => { let webpackConfig; @@ -587,9 +587,10 @@ describe("normalize options", () => { webpackConfig = require("./fixtures/multi-compiler-one-configuration/webpack.config"); if (Array.isArray(item.webpackConfig)) { - webpackConfig = item.webpackConfig.map((config, index) => { - return { ...webpackConfig[index], ...config }; - }); + webpackConfig = item.webpackConfig.map((config, index) => ({ + ...webpackConfig[index], + ...config, + })); } } else { webpackConfig = require("./fixtures/simple-config/webpack.config"); @@ -622,23 +623,21 @@ describe("normalize options", () => { optionsForSnapshot.port = ""; if (optionsForSnapshot.static.length > 0) { - optionsForSnapshot.static.forEach((i) => { + for (const i of optionsForSnapshot.static) { i.directory = i.directory - .replace(/\\/g, "/") - .replace( - new RegExp(process.cwd().replace(/\\/g, "/"), "g"), + .replaceAll("\\", "/") + .replaceAll( + new RegExp(process.cwd().replaceAll("\\", "/"), "g"), "", ); - }); + } } expect(optionsForSnapshot).toMatchSnapshot(); } - } catch (error) { - throw error; } finally { await server.stop(); } }); - }); + } }); diff --git a/test/ports-map.js b/test/ports-map.js index b3a3bc313a..d95dc62af9 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -88,14 +88,15 @@ let startPort = 8089; const ports = {}; -Object.keys(listOfTests).forEach((key) => { +for (const key of Object.keys(listOfTests)) { const value = listOfTests[key]; ports[key] = value === 1 ? (startPort += 1) - : [...new Array(value)].map(() => (startPort += 1)); -}); + : // eslint-disable-next-line no-loop-func + Array.from({ length: value }).map(() => (startPort += 1)); +} const busy = {}; diff --git a/test/server/open-option.test.js b/test/server/open-option.test.js index c31d8c0372..27e29ca815 100644 --- a/test/server/open-option.test.js +++ b/test/server/open-option.test.js @@ -17,11 +17,9 @@ if (needRequireMock) { jest.mock("open"); - open.mockImplementation(() => { - return { - catch: jest.fn(), - }; - }); + open.mockImplementation(() => ({ + catch: jest.fn(), + })); } describe('"open" option', () => { @@ -31,11 +29,9 @@ describe('"open" option', () => { compiler = webpack(config); if (!needRequireMock) { - jest.unstable_mockModule("open", () => { - return { - default: jest.fn(() => Promise.resolve()), - }; - }); + jest.unstable_mockModule("open", () => ({ + default: jest.fn(() => Promise.resolve()), + })); open = (await import("open")).default; } @@ -736,18 +732,16 @@ describe('"open" option', () => { }); it("should log warning when can't open", async () => { - open.mockImplementation(() => Promise.reject()); + open.mockRejectedValue(undefined); const loggerWarnSpy = jest.fn(); const getInfrastructureLoggerSpy = jest .spyOn(compiler, "getInfrastructureLogger") - .mockImplementation(() => { - return { - warn: loggerWarnSpy, - info: () => {}, - log: () => {}, - }; - }); + .mockImplementation(() => ({ + warn: loggerWarnSpy, + info: () => {}, + log: () => {}, + })); const server = new Server( { @@ -772,18 +766,16 @@ describe('"open" option', () => { }); it("should log warning when can't open with string", async () => { - open.mockImplementation(() => Promise.reject()); + open.mockRejectedValue(undefined); const loggerWarnSpy = jest.fn(); const getInfrastructureLoggerSpy = jest .spyOn(compiler, "getInfrastructureLogger") - .mockImplementation(() => { - return { - warn: loggerWarnSpy, - info: () => {}, - log: () => {}, - }; - }); + .mockImplementation(() => ({ + warn: loggerWarnSpy, + info: () => {}, + log: () => {}, + })); const server = new Server( { @@ -808,18 +800,16 @@ describe('"open" option', () => { }); it("should log warning when can't open with object", async () => { - open.mockImplementation(() => Promise.reject()); + open.mockRejectedValue(undefined); const loggerWarnSpy = jest.fn(); const getInfrastructureLoggerSpy = jest .spyOn(compiler, "getInfrastructureLogger") - .mockImplementation(() => { - return { - warn: loggerWarnSpy, - info: () => {}, - log: () => {}, - }; - }); + .mockImplementation(() => ({ + warn: loggerWarnSpy, + info: () => {}, + log: () => {}, + })); const server = new Server( { @@ -848,18 +838,16 @@ describe('"open" option', () => { }); it("should log warning when can't open with object with the 'app' option with arguments", async () => { - open.mockImplementation(() => Promise.reject()); + open.mockRejectedValue(undefined); const loggerWarnSpy = jest.fn(); const getInfrastructureLoggerSpy = jest .spyOn(compiler, "getInfrastructureLogger") - .mockImplementation(() => { - return { - warn: loggerWarnSpy, - info: () => {}, - log: () => {}, - }; - }); + .mockImplementation(() => ({ + warn: loggerWarnSpy, + info: () => {}, + log: () => {}, + })); const server = new Server( { @@ -894,18 +882,16 @@ describe('"open" option', () => { }); it("should log warning when can't open with object with the 'app' option with arguments", async () => { - open.mockImplementation(() => Promise.reject()); + open.mockRejectedValue(undefined); const loggerWarnSpy = jest.fn(); const getInfrastructureLoggerSpy = jest .spyOn(compiler, "getInfrastructureLogger") - .mockImplementation(() => { - return { - warn: loggerWarnSpy, - info: () => {}, - log: () => {}, - }; - }); + .mockImplementation(() => ({ + warn: loggerWarnSpy, + info: () => {}, + log: () => {}, + })); const server = new Server( { diff --git a/test/server/proxy-option.test.js b/test/server/proxy-option.test.js index e77824a371..71ad20254f 100644 --- a/test/server/proxy-option.test.js +++ b/test/server/proxy-option.test.js @@ -1,12 +1,12 @@ "use strict"; -const path = require("path"); -const util = require("util"); -const request = require("supertest"); -const express = require("express"); +const path = require("node:path"); +const util = require("node:util"); const bodyParser = require("body-parser"); -const WebSocket = require("ws"); +const express = require("express"); +const request = require("supertest"); const webpack = require("webpack"); +const WebSocket = require("ws"); const Server = require("../../lib/Server"); const config = require("../fixtures/proxy-config/webpack.config"); const [port1, port2, port3, port4] = require("../ports-map")["proxy-option"]; @@ -79,10 +79,9 @@ let maxServerListeners = 0; const proxyOptionOfArray = [ { context: "/proxy1", target: `http://localhost:${port1}` }, function proxy(req, res, next) { - if (req != null) { - const socket = req.socket != null ? req.socket : req.connection; - // @ts-ignore - const server = socket != null ? socket.server : null; + if (req !== null) { + const socket = req.socket !== null ? req.socket : req.connection; + const server = socket !== null ? socket.server : null; if (server) { maxServerListeners = Math.max( maxServerListeners, @@ -218,7 +217,7 @@ describe("proxy option", () => { it("respects a proxy option when a request path is matched", async () => { const response = await req.get("/proxy1"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy1"); }); }); @@ -227,7 +226,7 @@ describe("proxy option", () => { it("respects a pathRewrite option", async () => { const response = await req.get("/api/proxy2"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy2"); }); }); @@ -238,15 +237,15 @@ describe("proxy option", () => { const response = await req.get("/foo/bar.html"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("Hello"); const lastCall = utilSpy.mock.calls[utilSpy.mock.calls.length - 1]; - expect(lastCall[1]).toEqual( + expect(lastCall[1]).toBe( "Using the 'bypass' option is deprecated. Please use the 'router' or 'context' options. Read more at https://github.com/chimurai/http-proxy-middleware/tree/v2.0.6#http-proxy-middleware-options", ); - expect(lastCall[2]).toEqual( + expect(lastCall[2]).toBe( "DEP_WEBPACK_DEV_SERVER_PROXY_BYPASS_ARGUMENT", ); @@ -256,47 +255,47 @@ describe("proxy option", () => { it("can rewrite a request path", async () => { const response = await req.get("/foo/bar.html"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("Hello"); }); it("can rewrite a request path regardless of the target defined a bypass option", async () => { const response = await req.get("/baz/hoge.html"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("Hello"); }); it("should pass through a proxy when a bypass function returns null", async () => { const response = await req.get("/foo.js"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("Hey"); }); it("should not pass through a proxy when a bypass function returns false", async () => { const response = await req.get("/proxyfalse"); - expect(response.status).toEqual(404); + expect(response.status).toBe(404); }); it("should wait if bypass returns promise", async () => { const response = await req.get("/proxy/async"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("proxy async response"); }); it("should work with the 'target' option", async () => { const response = await req.get("/bypass-with-target/foo.js"); - expect(response.status).toEqual(404); + expect(response.status).toBe(404); }); it("should work with the 'target' option #2", async () => { const response = await req.get("/bypass-with-target/index.html"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("Hello"); }); }); @@ -332,7 +331,7 @@ describe("proxy option", () => { it("respects a proxy option", async () => { const response = await req.get("/proxy1"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy1"); }); }); @@ -367,7 +366,7 @@ describe("proxy option", () => { it("respects a proxy option", async () => { const response = await req.get("/proxy1"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy1"); }); }); @@ -402,7 +401,7 @@ describe("proxy option", () => { it("respects a proxy option", async () => { const response = await req.get("/proxy1"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy1"); }); }); @@ -437,7 +436,7 @@ describe("proxy option", () => { it("respects a proxy option", async () => { const response = await req.get("/proxy1"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy1"); }); }); @@ -472,22 +471,22 @@ describe("proxy option", () => { it("respects a proxy option", async () => { const response = await req.get("/proxy1"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy1"); }); it("respects a proxy option of function", async () => { const response = await req.get("/api/proxy2"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy2"); }); it("should allow req, res, and next", async () => { const response = await req.get("/api/proxy2?foo=true"); - expect(response.statusCode).toEqual(200); - expect(response.text).toEqual("foo+next+function"); + expect(response.statusCode).toBe(200); + expect(response.text).toBe("foo+next+function"); }); it("should not exist multiple close events registered", async () => { @@ -525,7 +524,7 @@ describe("proxy option", () => { it("respects a proxy option", async () => { const response = await req.get("/proxy1"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy1"); }); }); @@ -580,14 +579,14 @@ describe("proxy option", () => { it("respects proxy1 option", async () => { const response = await req.get("/proxy1"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy"); }); it("respects proxy2 option", async () => { const response = await req.get("/proxy2"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy"); }); }); @@ -600,7 +599,8 @@ describe("proxy option", () => { const webSocketServerTypes = ["sockjs", "ws"]; - webSocketServerTypes.forEach((webSocketServerType) => { + for (const webSocketServerType of webSocketServerTypes) { + // eslint-disable-next-line no-loop-func describe(`with webSocketServerType: ${webSocketServerType}`, () => { beforeAll(async () => { const compiler = webpack(config); @@ -643,10 +643,6 @@ describe("proxy option", () => { }); }); - it("Should receive response", () => { - expect(responseMessage).toEqual("foo"); - }); - afterAll(async () => { webSocketServer.close(); @@ -656,8 +652,12 @@ describe("proxy option", () => { await server.stop(); }); + + it("should receive response", () => { + expect(responseMessage).toBe("foo"); + }); }); - }); + } }); describe("should supports http methods", () => { @@ -713,13 +713,13 @@ describe("proxy option", () => { }); proxy.post("/post-x-www-form-urlencoded", (proxyReq, res) => { - const id = proxyReq.body.id; + const { id } = proxyReq.body; res.status(200).send(`POST method from proxy (id: ${id})`); }); proxy.post("/post-application-json", (proxyReq, res) => { - const id = proxyReq.body.id; + const { id } = proxyReq.body; res.status(200).send({ answer: `POST method from proxy (id: ${id})` }); }); @@ -745,49 +745,49 @@ describe("proxy option", () => { it("errors", async () => { const response = await req.get("/%"); - expect(response.status).toEqual(500); + expect(response.status).toBe(500); expect(response.text).toContain("error from proxy"); }); - it("GET method", async () => { + it("gET method", async () => { const response = await req.get("/get"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("GET method from proxy"); }); - it("HEAD method", async () => { + it("hEAD method", async () => { const response = await req.head("/head"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); }); - it("POST method (application/x-www-form-urlencoded)", async () => { + it("pOST method (application/x-www-form-urlencoded)", async () => { const response = await req .post("/post-x-www-form-urlencoded") .send("id=1"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("POST method from proxy (id: 1)"); }); - it("POST method (application/json)", async () => { + it("pOST method (application/json)", async () => { const response = await req .post("/post-application-json") .send({ id: "1" }) .set("Accept", "application/json"); - expect(response.status).toEqual(200); - expect(response.headers["content-type"]).toEqual( + expect(response.status).toBe(200); + expect(response.headers["content-type"]).toBe( "application/json; charset=utf-8", ); expect(response.text).toContain("POST method from proxy (id: 1)"); }); - it("DELETE method", async () => { + it("dELETE method", async () => { const response = await req.delete("/delete"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("DELETE method from proxy"); }); }); @@ -827,7 +827,7 @@ describe("proxy option", () => { it("respects a proxy option", async () => { const response = await req.get("/proxy1"); - expect(response.status).toEqual(200); + expect(response.status).toBe(200); expect(response.text).toContain("from proxy1"); }); }); diff --git a/test/validate-options.test.js b/test/validate-options.test.js index bc170f3dc3..d8f9ccfa47 100644 --- a/test/validate-options.test.js +++ b/test/validate-options.test.js @@ -1,10 +1,10 @@ "use strict"; -const os = require("os"); -const path = require("path"); +const os = require("node:os"); +const path = require("node:path"); const { readFileSync } = require("graceful-fs"); +const { Volume, createFsFromVolume } = require("memfs"); const webpack = require("webpack"); -const { createFsFromVolume, Volume } = require("memfs"); const Server = require("../lib/Server"); const config = require("./fixtures/simple-config/webpack.config"); @@ -555,9 +555,9 @@ const tests = { }, }; -describe("options", () => { - jest.setTimeout(20000); +jest.setTimeout(20000); +describe("options", () => { let consoleMock; beforeAll(() => { @@ -585,9 +585,9 @@ describe("options", () => { if (typeof replacedValue === "string") { replacedValue = replacedValue - .replace(/\\/g, "/") - .replace( - new RegExp(process.cwd().replace(/\\/g, "/"), "g"), + .replaceAll("\\", "/") + .replaceAll( + new RegExp(process.cwd().replaceAll("\\", "/"), "g"), "", ); } @@ -618,7 +618,7 @@ describe("options", () => { if (type === "success") { expect(thrownError).toBeUndefined(); } else { - expect(thrownError).not.toBeUndefined(); + expect(thrownError).toBeDefined(); expect(thrownError.toString()).toMatchSnapshot(); } }); diff --git a/types/lib/Server.d.ts b/types/lib/Server.d.ts index db75276fe2..41b09a245e 100644 --- a/types/lib/Server.d.ts +++ b/types/lib/Server.d.ts @@ -1,6 +1,6 @@ export = Server; /** - * @typedef {Object} BasicApplication + * @typedef {object} BasicApplication * @property {typeof useFn} use */ /** @@ -1178,7 +1178,7 @@ declare class Server< compiler: import("webpack").Compiler | import("webpack").MultiCompiler; /** * @type {ReturnType} - * */ + */ logger: ReturnType; options: Configuration; /** @@ -1253,7 +1253,7 @@ declare class Server< * @returns {Promise} */ private setupApp; - /** @type {A | undefined}*/ + /** @type {A | undefined} */ app: A | undefined; /** * @private @@ -1304,7 +1304,7 @@ declare class Server< * @returns {Promise} */ private createServer; - /** @type {S | undefined}*/ + /** @type {S | undefined} */ server: S | undefined; isTlsServer: boolean | undefined; /** @@ -1331,6 +1331,7 @@ declare class Server< */ private bonjour; /** + * @param callback * @private * @returns {void} */ diff --git a/types/lib/getPort.d.ts b/types/lib/getPort.d.ts index 358ae2c81d..b1e91d14ca 100644 --- a/types/lib/getPort.d.ts +++ b/types/lib/getPort.d.ts @@ -2,7 +2,7 @@ export = getPorts; /** * @param {number} basePort * @param {string=} host - * @return {Promise} + * @returns {Promise} */ declare function getPorts( basePort: number, From 2ae34293f731c29a965ed4088e543e955fbce135 Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Mon, 14 Jul 2025 19:42:56 +0300 Subject: [PATCH 2/8] chore: initial work --- .eslintignore | 8 - .eslintrc.js | 86 ---- bin/webpack-dev-server.js | 6 +- client-src/index.js | 2 - client-src/modules/logger/tapable.js | 1 - client-src/modules/sockjs-client/index.js | 1 - client-src/overlay.js | 3 - client-src/socket.js | 5 - examples/util.js | 2 - jest.config.js | 1 + lib/Server.js | 478 +++++++++++---------- lib/getPort.js | 33 +- lib/servers/BaseServer.js | 2 +- lib/servers/SockJSServer.js | 25 +- lib/servers/WebsocketServer.js | 14 +- migration-v4.md | 41 +- migration-v5.md | 24 +- package-lock.json | 13 +- package.json | 8 +- scripts/extend-webpack-types.js | 10 +- scripts/globalSetupTest.js | 3 +- scripts/prepare-test-for-old-node.js | 3 +- scripts/setupTest.js | 2 + test/cli/basic.test.js | 19 +- test/cli/historyApiFallback-option.test.js | 2 +- test/cli/host-option.test.js | 19 +- test/cli/server-option.test.js | 29 +- test/client/clients/SockJSClient.test.js | 11 +- test/e2e/allowed-hosts.test.js | 40 -- test/e2e/api.test.js | 34 +- test/e2e/client-reconnect.test.js | 20 +- test/e2e/cross-origin-request.test.js | 8 - test/e2e/entry.test.js | 23 +- test/e2e/host.test.js | 7 +- test/e2e/hot-and-live-reload.test.js | 6 +- test/e2e/ipc.test.js | 1 + test/e2e/module-federation.test.js | 2 +- test/e2e/options-middleware.test.js | 2 - test/e2e/overlay.test.js | 27 +- test/e2e/server.test.js | 83 ---- test/e2e/static-directory.test.js | 22 +- test/e2e/stats.test.js | 2 +- test/e2e/web-socket-communication.test.js | 11 +- test/helpers/conditional-test.js | 3 + test/helpers/run-browser.js | 27 +- test/server/open-option.test.js | 3 +- test/validate-options.test.js | 2 - types/bin/webpack-dev-server.d.ts | 2 +- types/lib/Server.d.ts | 358 ++++++++------- types/lib/getPort.d.ts | 6 +- types/lib/servers/BaseServer.d.ts | 2 +- 51 files changed, 676 insertions(+), 866 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.js diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 9bc9ffb002..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,8 +0,0 @@ -/client -/dist -!/test/client -coverage -node_modules -examples/**/main.js -examples/client/trusted-types-overlay/app.js -test/fixtures/reload-config/foo.js diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 24127cd2b2..0000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,86 +0,0 @@ -"use strict"; - -module.exports = { - extends: ["webpack", "prettier"], - parser: "@babel/eslint-parser", - parserOptions: { - sourceType: "script", - ecmaVersion: 2018, - }, - reportUnusedDisableDirectives: true, - env: { - node: true, - es6: true, - }, - rules: { - curly: "error", - "consistent-return": "off", - "no-param-reassign": "off", - "no-underscore-dangle": "off", - "prefer-destructuring": ["error", { object: false, array: false }], - "prefer-rest-params": "off", - strict: ["error", "safe"], - "global-require": "off", - "spaced-comment": [ - "error", - "always", - { - line: { - exceptions: ["-", "+"], - markers: ["=", "!", "/"], - }, - block: { - exceptions: ["-", "+"], - markers: ["=", "!"], - balanced: false, - }, - }, - ], - }, - overrides: [ - { - files: ["client-src/**/*.js"], - excludedFiles: [ - "client-src/webpack.config.js", - "client-src/modules/logger/SyncBailHookFake.js", - ], - parserOptions: { - sourceType: "module", - allowImportExportEverywhere: true, - }, - env: { - browser: true, - }, - rules: { - "import/extensions": ["error", "always"], - }, - }, - { - files: ["test/**/*.js"], - rules: { - "no-console": "off", - }, - }, - { - files: [ - "test/client/**/*.js", - "test/e2e/**/*.js", - "test/fixtures/**/*.js", - "test/server/liveReload-option.test.js", - ], - env: { - browser: true, - node: true, - }, - }, - { - files: ["examples/**/*.js"], - env: { - browser: true, - }, - rules: { - "no-console": "off", - }, - }, - ], -}; diff --git a/bin/webpack-dev-server.js b/bin/webpack-dev-server.js index ede7e84215..de0cfd3b32 100755 --- a/bin/webpack-dev-server.js +++ b/bin/webpack-dev-server.js @@ -59,7 +59,7 @@ const isInstalled = (packageName) => { } while (dir !== (dir = path.dirname(dir))); // https://github.com/nodejs/node/blob/v18.9.1/lib/internal/modules/cjs/loader.js#L1274 - // @ts-ignore + // @ts-expect-error for (const internalPath of require("node:module").globalPaths) { try { if (fs.statSync(path.join(internalPath, packageName)).isDirectory()) { @@ -107,7 +107,7 @@ const runCli = (cli) => { * @property {string} binName name of the executable file * @property {boolean} installed currently installed? * @property {string} url homepage - * @property {Function} preprocess preprocessor + * @property {() => void} preprocess preprocessor */ /** @type {CliOption} */ @@ -186,7 +186,7 @@ if (!cli.installed) { }')...`, ); - runCommand(packageManager, installOptions.concat(cli.package)) + runCommand(packageManager, [...installOptions, cli.package]) .then(() => { runCli(cli); }) diff --git a/client-src/index.js b/client-src/index.js index c9ea5d1233..f4e1597500 100644 --- a/client-src/index.js +++ b/client-src/index.js @@ -44,7 +44,6 @@ const decodeOverlayOptions = (overlayOptions) => { overlayOptions[property], ); - // eslint-disable-next-line no-new-func overlayOptions[property] = new Function( "message", `var callback = ${overlayFilterFunctionString} @@ -60,7 +59,6 @@ const decodeOverlayOptions = (overlayOptions) => { */ const status = { isUnloading: false, - // eslint-disable-next-line camelcase currentHash: __webpack_hash__, }; diff --git a/client-src/modules/logger/tapable.js b/client-src/modules/logger/tapable.js index 2ee5f3accf..9cc27e00a2 100644 --- a/client-src/modules/logger/tapable.js +++ b/client-src/modules/logger/tapable.js @@ -7,5 +7,4 @@ function SyncBailHook() { /** * Client stub for tapable SyncBailHook */ -// eslint-disable-next-line import/prefer-default-export export { SyncBailHook }; diff --git a/client-src/modules/sockjs-client/index.js b/client-src/modules/sockjs-client/index.js index 36783ebda3..96035e03ab 100644 --- a/client-src/modules/sockjs-client/index.js +++ b/client-src/modules/sockjs-client/index.js @@ -1,2 +1 @@ -// eslint-disable-next-line import/no-extraneous-dependencies export { default } from "sockjs-client"; diff --git a/client-src/overlay.js b/client-src/overlay.js index c4ceb97e5b..0aa13e4648 100644 --- a/client-src/overlay.js +++ b/client-src/overlay.js @@ -37,7 +37,6 @@ const replaceUsingRegExp = (macroText, macroRegExp, macroReplacer) => { const replaceInput = replaceMatch[0]; replaceResult += macroReplacer(replaceInput); replaceLastIndex = replaceMatch.index + replaceInput.length; - // eslint-disable-next-line no-cond-assign } while ((replaceMatch = macroRegExp.exec(macroText))); if (replaceLastIndex !== macroText.length) { @@ -393,7 +392,6 @@ const formatProblem = (type, item) => { body += item; } else { const file = item.file || ""; - // eslint-disable-next-line no-nested-ternary const moduleName = item.moduleName ? item.moduleName.indexOf("!") !== -1 ? `${item.moduleName.replace(/^(\s|\S)*!/, "")} (${item.moduleName})` @@ -503,7 +501,6 @@ const createOverlay = (options) => { closeButtonElement.innerText = "×"; closeButtonElement.ariaLabel = "Dismiss"; closeButtonElement.addEventListener("click", () => { - // eslint-disable-next-line no-use-before-define overlayService.send({ type: "DISMISS" }); }); diff --git a/client-src/socket.js b/client-src/socket.js index e9f34fa276..f0e8c3c22d 100644 --- a/client-src/socket.js +++ b/client-src/socket.js @@ -4,22 +4,18 @@ import WebSocketClient from "./clients/WebSocketClient.js"; import { log } from "./utils/log.js"; // this WebsocketClient is here as a default fallback, in case the client is not injected -/* eslint-disable camelcase */ const Client = - // eslint-disable-next-line no-nested-ternary typeof __webpack_dev_server_client__ !== "undefined" ? typeof __webpack_dev_server_client__.default !== "undefined" ? __webpack_dev_server_client__.default : __webpack_dev_server_client__ : WebSocketClient; -/* eslint-enable camelcase */ let retries = 0; let maxRetries = 10; // Initialized client is exported so external consumers can utilize the same instance // It is mutable to enforce singleton -// eslint-disable-next-line import/no-mutable-exports export let client = null; let timeout; @@ -56,7 +52,6 @@ const socket = function initSocket(url, handlers, reconnect) { if (retries < maxRetries) { // Exponentially increase timeout to reconnect. // Respectfully copied from the package `got`. - // eslint-disable-next-line no-restricted-properties const retryInMs = 1000 * Math.pow(2, retries) + Math.random() * 100; retries += 1; diff --git a/examples/util.js b/examples/util.js index fbf0133dda..dc1d97f771 100644 --- a/examples/util.js +++ b/examples/util.js @@ -1,7 +1,5 @@ "use strict"; -/* eslint-disable import/no-extraneous-dependencies */ - const path = require("node:path"); const fs = require("graceful-fs"); const HtmlWebpackPlugin = require("html-webpack-plugin"); diff --git a/jest.config.js b/jest.config.js index 7504c54d6b..197b147833 100644 --- a/jest.config.js +++ b/jest.config.js @@ -28,6 +28,7 @@ module.exports = { // // FIXME: this uuid moduleNameMapper workaround can be removed after sockjs > uuid@v9 release // https://github.com/uuidjs/uuid/pull/616#issuecomment-1206283882 + // eslint-disable-next-line n/no-extraneous-require "^uuid$": require.resolve("uuid"), }, }; diff --git a/lib/Server.js b/lib/Server.js index def7121652..dab20b9728 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -41,10 +41,13 @@ const schema = require("./options.json"); /** @typedef {import("express").Request} ExpressRequest */ /** @typedef {import("express").Response} ExpressResponse */ -/** @typedef {(err?: any) => void} NextFunction */ +// eslint-disable-next-line jsdoc/no-restricted-syntax +/** @typedef {any} EXPECTED_ANY */ + +/** @typedef {(err?: EXPECTED_ANY) => void} NextFunction */ /** @typedef {(req: IncomingMessage, res: ServerResponse) => void} SimpleHandleFunction */ /** @typedef {(req: IncomingMessage, res: ServerResponse, next: NextFunction) => void} NextHandleFunction */ -/** @typedef {(err: any, req: IncomingMessage, res: ServerResponse, next: NextFunction) => void} ErrorHandleFunction */ +/** @typedef {(err: EXPECTED_ANY, req: IncomingMessage, res: ServerResponse, next: NextFunction) => void} ErrorHandleFunction */ /** @typedef {SimpleHandleFunction | NextHandleFunction | ErrorHandleFunction} HandleFunction */ /** @typedef {import("https").ServerOptions & { spdy?: { plain?: boolean | undefined, ssl?: boolean | undefined, 'x-forwarded-for'?: string | undefined, protocol?: string | undefined, protocols?: string[] | undefined }}} ServerOptions */ @@ -80,17 +83,17 @@ const schema = require("./options.json"); /** * @typedef {object} WatchFiles - * @property {string | string[]} paths - * @property {WatchOptions & { aggregateTimeout?: number, ignored?: WatchOptions["ignored"], poll?: number | boolean }} [options] + * @property {string | string[]} paths paths + * @property {(WatchOptions & { aggregateTimeout?: number, ignored?: WatchOptions["ignored"], poll?: number | boolean })=} options options */ /** * @typedef {object} Static - * @property {string} [directory] - * @property {string | string[]} [publicPath] - * @property {boolean | ServeIndexOptions} [serveIndex] - * @property {ServeStaticOptions} [staticOptions] - * @property {boolean | WatchOptions & { aggregateTimeout?: number, ignored?: WatchOptions["ignored"], poll?: number | boolean }} [watch] + * @property {string=} directory directory + * @property {(string | string[])=} publicPath public path + * @property {(boolean | ServeIndexOptions)=} serveIndex serve index + * @property {ServeStaticOptions=} staticOptions static options + * @property {(boolean | WatchOptions & { aggregateTimeout?: number, ignored?: WatchOptions["ignored"], poll?: number | boolean })=} watch watch and watch options */ /** @@ -105,21 +108,21 @@ const schema = require("./options.json"); /** * @template {BasicApplication} [A=ExpressApplication] * @template {BasicServer} [S=import("http").Server] - * @typedef {"http" | "https" | "spdy" | "http2" | string | function(ServerOptions, A): S} ServerType + * @typedef {"http" | "https" | "spdy" | "http2" | string | ((serverOptions: ServerOptions, application: A) => S)} ServerType */ /** * @template {BasicApplication} [A=ExpressApplication] * @template {BasicServer} [S=import("http").Server] * @typedef {object} ServerConfiguration - * @property {ServerType} [type] - * @property {ServerOptions} [options] + * @property {ServerType=} type type + * @property {ServerOptions=} options options */ /** * @typedef {object} WebSocketServerConfiguration - * @property {"sockjs" | "ws" | string | Function} [type] - * @property {Record} [options] + * @property {("sockjs" | "ws" | string | (() => WebSocketServerConfiguration))=} type type + * @property {Record=} options options */ /** @@ -151,14 +154,14 @@ const schema = require("./options.json"); /** * @typedef {object} OpenApp - * @property {string} [name] - * @property {string[]} [arguments] + * @property {string=} name + * @property {string[]=} arguments */ /** * @typedef {object} Open - * @property {string | string[] | OpenApp} [app] - * @property {string | string[]} [target] + * @property {(string | string[] | OpenApp)=} app + * @property {(string | string[])=} target target */ /** @@ -169,12 +172,12 @@ const schema = require("./options.json"); /** * @typedef {object} WebSocketURL - * @property {string} [hostname] - * @property {string} [password] - * @property {string} [pathname] - * @property {number | string} [port] - * @property {string} [protocol] - * @property {string} [username] + * @property {string=} hostname hostname + * @property {string=} password password + * @property {string=} pathname pathname + * @property {(number | string)=} port port + * @property {string=} protocol protocol + * @property {string=} username username */ /** @@ -183,12 +186,12 @@ const schema = require("./options.json"); /** * @typedef {object} ClientConfiguration - * @property {"log" | "info" | "warn" | "error" | "none" | "verbose"} [logging] - * @property {boolean | { warnings?: OverlayMessageOptions, errors?: OverlayMessageOptions, runtimeErrors?: OverlayMessageOptions }} [overlay] - * @property {boolean} [progress] - * @property {boolean | number} [reconnect] - * @property {"ws" | "sockjs" | string} [webSocketTransport] - * @property {string | WebSocketURL} [webSocketURL] + * @property {"log" | "info" | "warn" | "error" | "none" | "verbose"=} logging logging + * @property {(boolean | { warnings?: OverlayMessageOptions, errors?: OverlayMessageOptions, runtimeErrors?: OverlayMessageOptions })=} overlay overlay + * @property {boolean=} progress progress + * @property {(boolean | number)=} reconnect reconnect + * @property {("ws" | "sockjs" | string)=} webSocketTransport web socket transport + * @property {(string | WebSocketURL)=} webSocketURL web socket URL */ /** @@ -214,28 +217,28 @@ const schema = require("./options.json"); * @template {BasicApplication} [A=ExpressApplication] * @template {BasicServer} [S=import("http").Server] * @typedef {object} Configuration - * @property {boolean | string} [ipc] - * @property {Host} [host] - * @property {Port} [port] - * @property {boolean | "only"} [hot] - * @property {boolean} [liveReload] - * @property {DevMiddlewareOptions} [devMiddleware] - * @property {boolean} [compress] - * @property {"auto" | "all" | string | string[]} [allowedHosts] - * @property {boolean | ConnectHistoryApiFallbackOptions} [historyApiFallback] - * @property {boolean | Record | BonjourOptions} [bonjour] - * @property {string | string[] | WatchFiles | Array} [watchFiles] - * @property {boolean | string | Static | Array} [static] - * @property {ServerType | ServerConfiguration} [server] - * @property {() => Promise} [app] - * @property {boolean | "sockjs" | "ws" | string | WebSocketServerConfiguration} [webSocketServer] - * @property {ProxyConfigArray} [proxy] - * @property {boolean | string | Open | Array} [open] - * @property {boolean} [setupExitSignals] - * @property {boolean | ClientConfiguration} [client] - * @property {Headers | ((req: Request, res: Response, context: DevMiddlewareContext | undefined) => Headers)} [headers] - * @property {(devServer: Server) => void} [onListening] - * @property {(middlewares: Middleware[], devServer: Server) => Middleware[]} [setupMiddlewares] + * @property {(boolean | string)=} ipc + * @property {Host=} host + * @property {Port=} port + * @property {(boolean | "only")=} hot + * @property {boolean=} liveReload + * @property {DevMiddlewareOptions=} devMiddleware + * @property {boolean=} compress + * @property {("auto" | "all" | string | string[])=} allowedHosts + * @property {(boolean | ConnectHistoryApiFallbackOptions)=} historyApiFallback + * @property {(boolean | Record | BonjourOptions)=} bonjour + * @property {(string | string[] | WatchFiles | Array)=} watchFiles + * @property {(boolean | string | Static | Array)=} static + * @property {(ServerType | ServerConfiguration)=} server + * @property {(() => Promise)=} app + * @property {(boolean | "sockjs" | "ws" | string | WebSocketServerConfiguration)=} webSocketServer + * @property {ProxyConfigArray=} proxy + * @property {(boolean | string | Open | Array)=} open + * @property {boolean=} setupExitSignals + * @property {(boolean | ClientConfiguration)=} client + * @property {(Headers | ((req: Request, res: Response, context: DevMiddlewareContext | undefined) => Headers))=} headers + * @property {((devServer: Server) => void)=} onListening + * @property {((middlewares: Middleware[], devServer: Server) => Middleware[])=} setupMiddlewares */ if (!process.env.WEBPACK_SERVE) { @@ -244,35 +247,38 @@ if (!process.env.WEBPACK_SERVE) { /** * @template T - * @param fn {(function(): any) | undefined} - * @returns {function(): T} + * @typedef {() => T} FunctionReturning + */ + +/** + * @template T + * @param {FunctionReturning} fn memorized function + * @returns {FunctionReturning} new function */ const memoize = (fn) => { let cache = false; - /** @type {T} */ + /** @type {T | undefined} */ let result; - return () => { if (cache) { - return result; + return /** @type {T} */ (result); } - result = /** @type {function(): any} */ (fn)(); + result = fn(); cache = true; // Allow to clean up memory for fn // and all dependent resources - - fn = undefined; - - return result; + /** @type {FunctionReturning | undefined} */ + (fn) = undefined; + return /** @type {T} */ (result); }; }; const getExpress = memoize(() => require("express")); /** - * @param {OverlayMessageOptions} [setting] - * @returns + * @param {OverlayMessageOptions=} setting overlay settings + * @returns {undefined | string | boolean} encoded overlay settings */ const encodeOverlaySettings = (setting) => typeof setting === "function" @@ -282,24 +288,24 @@ const encodeOverlaySettings = (setting) => // Working for overload, because typescript doesn't support this yes /** * @overload - * @param {NextHandleFunction} fn - * @returns {BasicApplication} + * @param {NextHandleFunction} fn function + * @returns {BasicApplication} application */ /** * @overload - * @param {HandleFunction} fn - * @returns {BasicApplication} + * @param {HandleFunction} fn function + * @returns {BasicApplication} application */ /** * @overload - * @param {string} route - * @param {NextHandleFunction} fn - * @returns {BasicApplication} + * @param {string} route route + * @param {NextHandleFunction} fn function + * @returns {BasicApplication} application */ /** - * @param {string} route - * @param {HandleFunction} fn - * @returns {BasicApplication} + * @param {string} route route + * @param {HandleFunction} fn function + * @returns {BasicApplication} application */ // eslint-disable-next-line no-unused-vars function useFn(route, fn) { @@ -319,10 +325,10 @@ const DEFAULT_ALLOWED_PROTOCOLS = /^(file|.+-extension):/i; */ class Server { /** - * @param {Configuration} options - * @param {Compiler | MultiCompiler} compiler + * @param {Configuration} options options + * @param {Compiler | MultiCompiler} compiler compiler */ - constructor(options = {}, compiler) { + constructor(options, compiler) { validate(/** @type {Schema} */ (schema), options, { name: "Dev Server", baseDataPath: "options", @@ -340,7 +346,7 @@ class Server { this.staticWatchers = []; /** * @private - * @type {{ name: string | symbol, listener: (...args: any[]) => void}[] }} + * @type {{ name: string | symbol, listener: (...args: EXPECTED_ANY[]) => void}[] }} */ this.listeners = []; // Keep track of websocket proxies for external websocket upgrade. @@ -367,8 +373,7 @@ class Server { /** * @private - * @returns {StatsOptions} - * @constructor + * @returns {StatsOptions} default stats options */ static get DEFAULT_STATS() { return { @@ -381,8 +386,8 @@ class Server { } /** - * @param {string} URL - * @returns {boolean} + * @param {string} URL url + * @returns {boolean} true when URL is absolute, otherwise false */ static isAbsoluteURL(URL) { // Don't match Windows paths `c:\` @@ -396,9 +401,9 @@ class Server { } /** - * @param {string} gatewayOrFamily or family - * @param {boolean} [isInternal] ip should be internal - * @returns {string | undefined} + * @param {string} gatewayOrFamily gateway or family + * @param {boolean=} isInternal ip should be internal + * @returns {string | undefined} resolved IP */ static findIp(gatewayOrFamily, isInternal) { if (gatewayOrFamily === "v4" || gatewayOrFamily === "v6") { @@ -462,6 +467,7 @@ class Server { if ( net[0] && net[0].kind() === gatewayIp.kind() && + // eslint-disable-next-line unicorn/prefer-regexp-test gatewayIp.match(net) ) { return net[0].toString(); @@ -472,8 +478,8 @@ class Server { // TODO remove me in the next major release, we have `findIp` /** - * @param {"v4" | "v6"} family - * @returns {Promise} + * @param {"v4" | "v6"} family family + * @returns {Promise} internal API */ static async internalIP(family) { return Server.findIp(family, false); @@ -481,16 +487,16 @@ class Server { // TODO remove me in the next major release, we have `findIp` /** - * @param {"v4" | "v6"} family - * @returns {string | undefined} + * @param {"v4" | "v6"} family family + * @returns {string | undefined} internal IP */ static internalIPSync(family) { return Server.findIp(family, false); } /** - * @param {Host} hostname - * @returns {Promise} + * @param {Host} hostname hostname + * @returns {Promise} resolved hostname */ static async getHostname(hostname) { if (hostname === "local-ip") { @@ -507,9 +513,9 @@ class Server { } /** - * @param {Port} port - * @param {string} host - * @returns {Promise} + * @param {Port} port port + * @param {string} host host + * @returns {Promise} free port */ static async getFreePort(port, host) { if (typeof port !== "undefined" && port !== null && port !== "auto") { @@ -538,7 +544,7 @@ class Server { } /** - * @returns {string} + * @returns {string} path to cache dir */ static findCacheDir() { const cwd = process.cwd(); @@ -577,8 +583,8 @@ class Server { /** * @private - * @param {Compiler} compiler - * @returns bool + * @param {Compiler} compiler compiler + * @returns {boolean} true when target is `web`, otherwise false */ static isWebTarget(compiler) { if (compiler.platform && compiler.platform.web) { @@ -621,7 +627,7 @@ class Server { /** * @private - * @param {Compiler} compiler + * @param {Compiler} compiler compiler */ addAdditionalEntries(compiler) { /** @@ -817,7 +823,7 @@ class Server { /** * @private - * @returns {Compiler["options"]} + * @returns {Compiler["options"]} compiler options */ getCompilerOptions() { if ( @@ -879,8 +885,8 @@ class Server { const compilerOptions = this.getCompilerOptions(); const compilerWatchOptions = compilerOptions.watchOptions; /** - * @param {WatchOptions & { aggregateTimeout?: number, ignored?: WatchOptions["ignored"], poll?: number | boolean }} watchOptions - * @returns {WatchOptions} + * @param {WatchOptions & { aggregateTimeout?: number, ignored?: WatchOptions["ignored"], poll?: number | boolean }} watchOptions watch options + * @returns {WatchOptions} normalized watch options */ const getWatchOptions = (watchOptions = {}) => { const getPolling = () => { @@ -932,8 +938,8 @@ class Server { }; }; /** - * @param {string | Static | undefined} [optionsForStatic] - * @returns {NormalizedStatic} + * @param {(string | Static | undefined)=} optionsForStatic for static + * @returns {NormalizedStatic} normalized options for static */ const getStaticItem = (optionsForStatic) => { const getDefaultStaticOptions = () => ({ @@ -978,7 +984,6 @@ class Server { // If 'serveIndex' is an object, merge its properties with default 'serveIndex' // If 'serveIndex' is neither a boolean true nor an object, use it as-is // If 'serveIndex' is not defined in 'optionsForStatic', use default 'serveIndex' - typeof optionsForStatic.serveIndex !== "undefined" ? typeof optionsForStatic.serveIndex === "boolean" && optionsForStatic.serveIndex @@ -1152,16 +1157,17 @@ class Server { /** @type {Array} */ (["ca", "cert", "crl", "key", "pfx"]); - for (const property of httpsProperties) { + for (const property_ of httpsProperties) { + const property = /** @type {keyof ServerOptions} */ (property_); + if (typeof serverOptions[property] === "undefined") { continue; } - /** @type {any} */ const value = serverOptions[property]; /** - * @param {string | Buffer | undefined} item - * @returns {string | Buffer | undefined} + * @param {string | Buffer | undefined} item file to read + * @returns {string | Buffer | undefined} content of file */ const readFile = (item) => { if ( @@ -1185,10 +1191,18 @@ class Server { } }; - /** @type {any} */ + /** @type {EXPECTED_ANY} */ (serverOptions)[property] = Array.isArray(value) - ? value.map((item) => readFile(item)) - : readFile(value); + ? value.map((item) => + readFile( + /** @type {string | Buffer | undefined} */ + (item), + ), + ) + : readFile( + /** @type {string | Buffer | undefined} */ + (value), + ); } let fakeCert; @@ -1306,8 +1320,8 @@ class Server { this.logger.info(`SSL certificate: ${certificatePath}`); } - serverOptions.key = serverOptions.key || fakeCert; - serverOptions.cert = serverOptions.cert || fakeCert; + serverOptions.key ||= fakeCert; + serverOptions.cert ||= fakeCert; } if (typeof options.ipc === "boolean") { @@ -1324,8 +1338,8 @@ class Server { // https://github.com/webpack/webpack-dev-server/issues/1990 const defaultOpenOptions = { wait: false }; /** - * @param {any} target - * @returns {NormalizedOpen[]} + * @param {import("open").Options & { target?: string | string[] } & EXPECTED_ANY} target target + * @returns {NormalizedOpen[]} normalized open options */ const getOpenItemsFromObject = ({ target, ...rest }) => { const normalizedOptions = { ...defaultOpenOptions, ...rest }; @@ -1393,13 +1407,9 @@ class Server { /** * Assume a proxy configuration specified as: - * proxy: { - * 'context': { options } - * } + * proxy: { 'context': { options } } * OR - * proxy: { - * 'context': 'target' - * } + * proxy: { 'context': 'target' } */ if (typeof options.proxy !== "undefined") { options.proxy = options.proxy.map((item) => { @@ -1408,8 +1418,8 @@ class Server { } /** - * @param {"info" | "warn" | "error" | "debug" | "silent" | undefined | "none" | "log" | "verbose"} level - * @returns {"info" | "warn" | "error" | "debug" | "silent" | undefined} + * @param {"info" | "warn" | "error" | "debug" | "silent" | undefined | "none" | "log" | "verbose"} level level + * @returns {"info" | "warn" | "error" | "debug" | "silent" | undefined} log level for proxy */ const getLogLevelForProxy = (level) => { if (level === "none") { @@ -1534,7 +1544,7 @@ class Server { /** * @private - * @returns {string} + * @returns {string} client transport */ getClientTransport() { let clientImplementation; @@ -1546,7 +1556,7 @@ class Server { /** @type {WebSocketServerConfiguration} */ (this.options.webSocketServer).type ) === "string" && - // @ts-ignore + // @ts-expect-error (this.options.webSocketServer.type === "ws" || /** @type {WebSocketServerConfiguration} */ (this.options.webSocketServer).type === "sockjs"); @@ -1613,7 +1623,7 @@ class Server { /** * @template T * @private - * @returns {T} + * @returns {T} server transport */ getServerTransport() { let implementation; @@ -1679,7 +1689,7 @@ class Server { } /** - * @returns {string | void} + * @returns {string | void} client hot entry */ getClientHotEntry() { if (this.options.hot === "only") { @@ -1702,10 +1712,10 @@ class Server { new ProgressPlugin( /** - * @param {number} percent - * @param {string} msg - * @param {string} addInfo - * @param {string} pluginName + * @param {number} percent percent + * @param {string} msg message + * @param {string} addInfo extra information + * @param {string} pluginName plugin name */ (percent, msg, addInfo, pluginName) => { percent = Math.floor(percent * 100); @@ -1763,7 +1773,9 @@ class Server { if (this.options.hot) { const HMRPluginExists = compiler.options.plugins.find( - (p) => p && p.constructor === webpack.HotModuleReplacementPlugin, + (plugin) => + plugin && + plugin.constructor === webpack.HotModuleReplacementPlugin, ); if (HMRPluginExists) { @@ -1797,8 +1809,10 @@ class Server { let needForceShutdown = false; for (const signal of signals) { + // eslint-disable-next-line no-loop-func const listener = () => { if (needForceShutdown) { + // eslint-disable-next-line n/no-process-exit process.exit(); } @@ -1811,9 +1825,11 @@ class Server { this.stopCallback(() => { if (typeof this.compiler.close === "function") { this.compiler.close(() => { + // eslint-disable-next-line n/no-process-exit process.exit(); }); } else { + // eslint-disable-next-line n/no-process-exit process.exit(); } }); @@ -1848,24 +1864,30 @@ class Server { async setupApp() { /** @type {A | undefined} */ this.app = - typeof this.options.app === "function" - ? await this.options.app() - : getExpress()(); + /** @type {A} */ + ( + typeof this.options.app === "function" + ? await this.options.app() + : getExpress()() + ); } /** * @private - * @param {Stats | MultiStats} statsObj - * @returns {StatsCompilation} + * @param {Stats | MultiStats} statsObj stats + * @returns {StatsCompilation} stats of compilation */ getStats(statsObj) { const stats = Server.DEFAULT_STATS; const compilerOptions = this.getCompilerOptions(); - // @ts-ignore - if (compilerOptions.stats && compilerOptions.stats.warningsFilter) { - // @ts-ignore - stats.warningsFilter = compilerOptions.stats.warningsFilter; + if ( + compilerOptions.stats && + /** @type {StatsOptions} */ (compilerOptions.stats).warningsFilter + ) { + stats.warningsFilter = + /** @type {StatsOptions} */ + (compilerOptions.stats).warningsFilter; } return statsObj.toJson(stats); @@ -1884,7 +1906,7 @@ class Server { this.compiler.hooks.done.tap( "webpack-dev-server", /** - * @param {Stats | MultiStats} stats + * @param {Stats | MultiStats} stats stats */ (stats) => { if (this.webSocketServer) { @@ -1944,9 +1966,9 @@ class Server { middlewares.push({ name: "host-header-check", /** - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function * @returns {void} */ middleware: (req, res, next) => { @@ -1969,9 +1991,9 @@ class Server { middlewares.push({ name: "cross-origin-header-check", /** - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function * @returns {void} */ middleware: (req, res, next) => { @@ -2045,9 +2067,9 @@ class Server { name: "webpack-dev-server-sockjs-bundle", path: "/__webpack_dev_server__/sockjs.bundle.js", /** - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function * @returns {void} */ middleware: (req, res, next) => { @@ -2094,9 +2116,9 @@ class Server { name: "webpack-dev-server-invalidate", path: "/webpack-dev-server/invalidate", /** - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function * @returns {void} */ middleware: (req, res, next) => { @@ -2115,9 +2137,9 @@ class Server { name: "webpack-dev-server-open-editor", path: "/webpack-dev-server/open-editor", /** - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function * @returns {void} */ middleware: (req, res, next) => { @@ -2136,7 +2158,6 @@ class Server { const fileName = params.get("fileName"); if (typeof fileName === "string") { - // @ts-ignore const launchEditor = require("launch-editor"); launchEditor(fileName); @@ -2150,9 +2171,9 @@ class Server { name: "webpack-dev-server-assets", path: "/webpack-dev-server", /** - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function * @returns {void} */ middleware: (req, res, next) => { @@ -2233,8 +2254,8 @@ class Server { const { createProxyMiddleware } = require("http-proxy-middleware"); /** - * @param {ProxyConfigArrayItem} proxyConfig - * @returns {RequestHandler | undefined} + * @param {ProxyConfigArrayItem} proxyConfig proxy config + * @returns {RequestHandler | undefined} request handler */ const getProxyMiddleware = (proxyConfig) => { // It is possible to use the `bypass` method without a `target` or `router`. @@ -2263,6 +2284,7 @@ class Server { }; /** + * @example * Assume a proxy configuration specified as: * proxy: [ * { @@ -2298,9 +2320,9 @@ class Server { } /** - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function * @returns {Promise} */ const handler = async (req, res, next) => { @@ -2310,9 +2332,9 @@ class Server { if (newProxyConfig !== proxyConfig) { proxyConfig = newProxyConfig; - const socket = req.socket != null ? req.socket : req.connection; - // @ts-ignore - const server = socket != null ? socket.server : null; + const socket = req.socket !== null ? req.socket : req.connection; + // @ts-expect-error + const server = socket !== null ? socket.server : null; if (server) { server.removeAllListeners("close"); @@ -2370,11 +2392,11 @@ class Server { name: "http-proxy-middleware-error-handler", middleware: /** - * @param {Error} error - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next - * @returns {any} + * @param {Error} error error + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function + * @returns {Promise} nothing */ (error, req, res, next) => handler(req, res, next), }); @@ -2420,7 +2442,7 @@ class Server { (historyApiFallback).verbose ) ) { - // @ts-ignore + // @ts-expect-error historyApiFallback.logger = this.logger.log.bind( this.logger, "[connect-history-api-fallback]", @@ -2469,9 +2491,9 @@ class Server { name: "serve-index", path: publicPath, /** - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function * @returns {void} */ middleware: (req, res, next) => { @@ -2497,9 +2519,9 @@ class Server { middlewares.push({ name: "options-middleware", /** - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function * @returns {void} */ middleware: (req, res, next) => { @@ -2606,7 +2628,7 @@ class Server { (this.server).on( "connection", /** - * @param {Socket} socket + * @param {Socket} socket connected socket */ (socket) => { // Add socket to list @@ -2623,7 +2645,7 @@ class Server { (this.server).on( "error", /** - * @param {Error} error + * @param {Error} error error */ (error) => { throw error; @@ -2643,8 +2665,8 @@ class Server { (this.webSocketServer).implementation.on( "connection", /** - * @param {ClientConnection} client - * @param {IncomingMessage} request + * @param {ClientConnection} client client + * @param {IncomingMessage} request request */ (client, request) => { /** @type {{ [key: string]: string | undefined } | undefined} */ @@ -2753,7 +2775,7 @@ class Server { /** * @private - * @param {string} defaultOpenTarget + * @param {string} defaultOpenTarget default open target * @returns {Promise} */ async openBrowser(defaultOpenTarget) { @@ -2823,8 +2845,8 @@ class Server { } /** - * @param callback * @private + * @param {() => void} callback callback * @returns {void} */ stopBonjour(callback = () => {}) { @@ -2847,8 +2869,8 @@ class Server { const { cyan, isColorSupported, red } = require("colorette"); /** - * @param {Compiler["options"]} compilerOptions - * @returns {boolean} + * @param {Compiler["options"]} compilerOptions compiler options + * @returns {boolean} value of the color option */ const getColorsOption = (compilerOptions) => { /** @@ -2873,9 +2895,9 @@ class Server { const colors = { /** - * @param {boolean} useColor - * @param {string} msg - * @returns {string} + * @param {boolean} useColor need to use color? + * @param {string} msg message + * @returns {string} message with color */ info(useColor, msg) { if (useColor) { @@ -2885,9 +2907,9 @@ class Server { return msg; }, /** - * @param {boolean} useColor - * @param {string} msg - * @returns {string} + * @param {boolean} useColor need to use color? + * @param {string} msg message + * @returns {string} message with colors */ error(useColor, msg) { if (useColor) { @@ -2909,8 +2931,8 @@ class Server { /** @type {import("net").AddressInfo} */ (server.address()); /** - * @param {string} newHostname - * @returns {string} + * @param {string} newHostname new hostname + * @returns {string} prettified URL */ const prettyPrintURL = (newHostname) => url.format({ protocol, hostname: newHostname, port, pathname: "/" }); @@ -3064,9 +3086,9 @@ class Server { /** * @private - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function */ setHeaders(req, res, next) { let { headers } = this.options; @@ -3082,14 +3104,16 @@ class Server { } /** - * @type {{key: string, value: string}[]} + * @type {{ key: string, value: string }[]} */ const allHeaders = []; if (!Array.isArray(headers)) { for (const name in headers) { - // @ts-ignore - allHeaders.push({ key: name, value: headers[name] }); + allHeaders.push({ + key: name, + value: /** @type {string} */ (headers[name]), + }); } headers = allHeaders; @@ -3105,8 +3129,8 @@ class Server { /** * @private - * @param {string} value - * @returns {boolean} + * @param {string} value value + * @returns {boolean} true when host allowed, otherwise false */ isHostAllowed(value) { const { allowedHosts } = this.options; @@ -3159,10 +3183,10 @@ class Server { /** * @private - * @param {{ [key: string]: string | undefined }} headers - * @param {string} headerToCheck - * @param {boolean} validateHost - * @returns {boolean} + * @param {{ [key: string]: string | undefined }} headers headers + * @param {string} headerToCheck header to check + * @param {boolean} validateHost need to validate host + * @returns {boolean} true when host is valid, otherwise false */ isValidHost(headers, headerToCheck, validateHost = true) { if (this.options.allowedHosts === "all") { @@ -3182,6 +3206,8 @@ class Server { } // use the node url-parser to retrieve the hostname from the host-header. + // TODO resolve me in the next major release + // eslint-disable-next-line n/no-deprecated-api const { hostname } = url.parse( // if header doesn't have scheme, add // for parsing. /^(.+:)?\/\//.test(header) ? header : `//${header}`, @@ -3219,8 +3245,8 @@ class Server { /** * @private - * @param {{ [key: string]: string | undefined }} headers - * @returns {boolean} + * @param {{ [key: string]: string | undefined }} headers headers + * @returns {boolean} true when is same origin, otherwise false */ isSameOrigin(headers) { if (this.options.allowedHosts === "all") { @@ -3237,6 +3263,8 @@ class Server { return true; } + // TODO resolve me in the next major release + // eslint-disable-next-line n/no-deprecated-api const origin = url.parse(originHeader, false, true).hostname; if (origin === null) { @@ -3257,6 +3285,7 @@ class Server { return true; } + // eslint-disable-next-line n/no-deprecated-api const host = url.parse( // if hostHeader doesn't have scheme, add // for parsing. /^(.+:)?\/\//.test(hostHeader) ? hostHeader : `//${hostHeader}`, @@ -3276,12 +3305,11 @@ class Server { } /** - * @param {ClientConnection[]} clients - * @param {string} type - * @param {any} [data] - * @param {any} [params] + * @param {ClientConnection[]} clients clients + * @param {string} type type + * @param {EXPECTED_ANY=} data data + * @param {EXPECTED_ANY=} params params */ - sendMessage(clients, type, data, params) { for (const client of clients) { // `sockjs` uses `1` to indicate client is ready to accept data @@ -3295,9 +3323,9 @@ class Server { // Send stats to a socket or multiple sockets /** * @private - * @param {ClientConnection[]} clients - * @param {StatsCompilation} stats - * @param {boolean} [force] + * @param {ClientConnection[]} clients clients + * @param {StatsCompilation} stats stats + * @param {boolean=} force force */ sendStats(clients, stats, force) { const shouldEmit = @@ -3351,8 +3379,8 @@ class Server { } /** - * @param {string | string[]} watchPath - * @param {WatchOptions} [watchOptions] + * @param {string | string[]} watchPath watch path + * @param {WatchOptions=} watchOptions watch options */ watchFiles(watchPath, watchOptions) { const chokidar = require("chokidar"); @@ -3376,7 +3404,7 @@ class Server { } /** - * @param {import("webpack-dev-middleware").Callback} [callback] + * @param {import("webpack-dev-middleware").Callback=} callback callback */ invalidate(callback = () => {}) { if (this.middleware) { @@ -3400,7 +3428,7 @@ class Server { socket.on( "error", /** - * @param {Error & { code?: string }} error + * @param {Error & { code?: string }} error error */ (error) => { if (error.code === "ECONNREFUSED") { @@ -3479,7 +3507,7 @@ class Server { } /** - * @param {(err?: Error) => void} [callback] + * @param {((err?: Error) => void)=} callback callback */ startCallback(callback = () => {}) { this.start() @@ -3573,7 +3601,7 @@ class Server { } /** - * @param {(err?: Error) => void} [callback] + * @param {((err?: Error) => void)=} callback callback */ stopCallback(callback = () => {}) { this.stop() diff --git a/lib/getPort.js b/lib/getPort.js index 8be8874a54..23bc4e348a 100644 --- a/lib/getPort.js +++ b/lib/getPort.js @@ -13,7 +13,7 @@ const minPort = 1024; const maxPort = 65_535; /** - * @returns {Set} + * @returns {Set} local hosts */ const getLocalHosts = () => { const interfaces = os.networkInterfaces(); @@ -35,9 +35,9 @@ const getLocalHosts = () => { }; /** - * @param {number} basePort - * @param {string | undefined} host - * @returns {Promise} + * @param {number} basePort base port + * @param {string | undefined} host host + * @returns {Promise} resolved port */ const checkAvailablePort = (basePort, host) => new Promise((resolve, reject) => { @@ -57,9 +57,9 @@ const checkAvailablePort = (basePort, host) => }); /** - * @param {number} port - * @param {Set} hosts - * @returns {Promise} + * @param {number} port port + * @param {Set} hosts hosts + * @returns {Promise} resolved port */ const getAvailablePort = async (port, hosts) => { /** @@ -87,9 +87,9 @@ const getAvailablePort = async (port, hosts) => { }; /** - * @param {number} basePort - * @param {string=} host - * @returns {Promise} + * @param {number} basePort base port + * @param {string=} host host + * @returns {Promise} resolved port */ async function getPorts(basePort, host) { if (basePort < minPort || basePort > maxPort) { @@ -97,17 +97,16 @@ async function getPorts(basePort, host) { } let port = basePort; + const localhosts = getLocalHosts(); - let hosts; - if (host && !localhosts.has(host)) { - hosts = new Set([host]); - } else { - /* If the host is equivalent to localhost + const hosts = + host && !localhosts.has(host) + ? new Set([host]) + : /* If the host is equivalent to localhost we need to check every equivalent host else the port might falsely appear as available on some operating systems */ - hosts = localhosts; - } + localhosts; /** @type {Set} */ const portUnavailableErrors = new Set(["EADDRINUSE", "EACCES"]); while (port <= maxPort) { diff --git a/lib/servers/BaseServer.js b/lib/servers/BaseServer.js index 30858ba77e..9f5a18f4e0 100644 --- a/lib/servers/BaseServer.js +++ b/lib/servers/BaseServer.js @@ -6,7 +6,7 @@ // server implementation module.exports = class BaseServer { /** - * @param {import("../Server")} server + * @param {import("../Server")} server server */ constructor(server) { /** @type {import("../Server")} */ diff --git a/lib/servers/SockJSServer.js b/lib/servers/SockJSServer.js index fc2523ff85..5468355bd7 100644 --- a/lib/servers/SockJSServer.js +++ b/lib/servers/SockJSServer.js @@ -10,13 +10,13 @@ const BaseServer = require("./BaseServer"); // sockjs will remove Origin header, however Origin header is required for checking host. // See https://github.com/webpack/webpack-dev-server/issues/1604 for more information { - // @ts-ignore + // @ts-expect-error const SockjsSession = require("sockjs/lib/transport").Session; const { decorateConnection } = SockjsSession.prototype; /** - * @param {import("http").IncomingMessage} req + * @param {import("http").IncomingMessage} req request */ // eslint-disable-next-line func-names SockjsSession.prototype.decorateConnection = function (req) { @@ -37,7 +37,7 @@ const BaseServer = require("./BaseServer"); module.exports = class SockJSServer extends BaseServer { // options has: error (function), debug (function), server (http/s server), path (string) /** - * @param {import("../Server")} server + * @param {import("../Server")} server server */ constructor(server) { super(server); @@ -50,8 +50,8 @@ module.exports = class SockJSServer extends BaseServer { ); /** - * @param {NonNullable} options - * @returns {string} + * @param {NonNullable} options options + * @returns {string} sockjs URL */ const getSockjsUrl = (options) => { if (typeof options.sockjsUrl !== "undefined") { @@ -63,11 +63,12 @@ module.exports = class SockJSServer extends BaseServer { this.implementation = sockjs.createServer({ // Use provided up-to-date sockjs-client + // eslint-disable-next-line camelcase sockjs_url: getSockjsUrl(webSocketServerOptions), // Default logger is very annoy. Limit useless logs. /** - * @param {string} severity - * @param {string} line + * @param {string} severity severity + * @param {string} line line */ log: (severity, line) => { if (severity === "error") { @@ -81,8 +82,8 @@ module.exports = class SockJSServer extends BaseServer { }); /** - * @param {import("sockjs").ServerOptions & { path?: string }} options - * @returns {string | undefined} + * @param {import("sockjs").ServerOptions & { path?: string }} options options + * @returns {string | undefined} prefix */ const getPrefix = (options) => { if (typeof options.prefix !== "undefined") { @@ -103,10 +104,10 @@ module.exports = class SockJSServer extends BaseServer { ); this.implementation.on("connection", (client) => { - // @ts-ignore + // @ts-expect-error // Implement the the same API as for `ws` client.send = client.write; - // @ts-ignore + // @ts-expect-error client.terminate = client.close; this.clients.push(/** @type {ClientConnection} */ (client)); @@ -119,7 +120,7 @@ module.exports = class SockJSServer extends BaseServer { }); }); - // @ts-ignore + // @ts-expect-error this.implementation.close = (callback) => { callback(); }; diff --git a/lib/servers/WebsocketServer.js b/lib/servers/WebsocketServer.js index 6612f5a06f..b9071f4bd3 100644 --- a/lib/servers/WebsocketServer.js +++ b/lib/servers/WebsocketServer.js @@ -10,7 +10,7 @@ module.exports = class WebsocketServer extends BaseServer { static heartbeatInterval = 1000; /** - * @param {import("../Server")} server + * @param {import("../Server")} server server */ constructor(server) { super(server); @@ -35,9 +35,9 @@ module.exports = class WebsocketServer extends BaseServer { (this.server.server).on( "upgrade", /** - * @param {import("http").IncomingMessage} req - * @param {import("stream").Duplex} sock - * @param {Buffer} head + * @param {import("http").IncomingMessage} req request + * @param {import("stream").Duplex} sock socket + * @param {Buffer} head head */ (req, sock, head) => { if (!this.implementation.shouldHandle(req)) { @@ -53,7 +53,7 @@ module.exports = class WebsocketServer extends BaseServer { this.implementation.on( "error", /** - * @param {Error} err + * @param {Error} err error */ (err) => { this.server.logger.error(err.message); @@ -76,7 +76,7 @@ module.exports = class WebsocketServer extends BaseServer { this.implementation.on( "connection", /** - * @param {ClientConnection} client + * @param {ClientConnection} client client */ (client) => { this.clients.push(client); @@ -95,7 +95,7 @@ module.exports = class WebsocketServer extends BaseServer { client.on( "error", /** - * @param {Error} err + * @param {Error} err err */ (err) => { this.server.logger.error(err.message); diff --git a/migration-v4.md b/migration-v4.md index 9c1734fc27..344030d2bb 100644 --- a/migration-v4.md +++ b/migration-v4.md @@ -44,7 +44,7 @@ v3: ```js module.exports = { devServer: { - before (app, server, compiler) { + before(app, server, compiler) { app.get("/some/path", (req, res) => { res.json({ custom: "response" }); }); @@ -58,7 +58,7 @@ v4: ```js module.exports = { devServer: { - onBeforeSetupMiddleware (devServer) { + onBeforeSetupMiddleware(devServer) { devServer.app.get("/some/path", (req, res) => { res.json({ custom: "response" }); }); @@ -74,7 +74,7 @@ v3: ```js module.exports = { devServer: { - after (app, server, compiler) { + after(app, server, compiler) { app.get("/some/path", (req, res) => { res.json({ custom: "response" }); }); @@ -88,7 +88,7 @@ v4: ```js module.exports = { devServer: { - onAfterSetupMiddleware (devServer) { + onAfterSetupMiddleware(devServer) { devServer.app.get("/some/path", (req, res) => { res.json({ custom: "response" }); }); @@ -547,11 +547,9 @@ module.exports = { // `hot` and `client` options are disabled because we added them manually const server = new DevServer({ hot: false, client: false }, compiler); - (async () => { - await server.start(); + await server.start(); - console.log("Running"); - })(); + console.log("Running"); ``` ### Deprecations @@ -591,11 +589,9 @@ module.exports = { const devServerOptions = { host: "127.0.0.1", port: 8080 }; const devServer = new Server(devServerOptions, compiler); - (async () => { - await devServer.start(); + await devServer.start(); - console.log("Running"); - })(); + console.log("Running"); ``` ```js @@ -630,15 +626,13 @@ module.exports = { const devServerOptions = { host: "127.0.0.1", port: 8080 }; const devServer = new Server(devServerOptions, compiler); - (async () => { - await devServer.start(); + await devServer.start(); - console.log("Running"); + console.log("Running"); - await devServer.stop(); + await devServer.stop(); - console.log("Closed"); - })(); + console.log("Closed"); ``` ```js @@ -723,13 +717,20 @@ There are a lot of other bug fixes. v3: ```js - new WebpackDevServer(compiler, {...}) + new WebpackDevServer(compiler, { + /* Options */ + }); ``` v4: ```js - new WebpackDevServer({...}, compiler) + new WebpackDevServer( + { + /* Options */ + }, + compiler, + ); ``` - [See here](https://github.com/webpack/webpack-dev-server/tree/master/examples/api/simple) for an example of how to use `webpack-dev-server` through the Node.js API. diff --git a/migration-v5.md b/migration-v5.md index e2830d5eac..02640b1a87 100644 --- a/migration-v5.md +++ b/migration-v5.md @@ -90,20 +90,20 @@ This document serves as a migration guide for `webpack-dev-server@5.0.0`. module.exports = { // ... devServer: { - onAfterSetupMiddleware (devServer) { + onAfterSetupMiddleware(devServer) { if (!devServer) { throw new Error("webpack-dev-server is not defined"); } - + devServer.app.get("/some/after-path", (req, res) => { res.json({ custom: "response" }); }); }, - onBeforeSetupMiddleware (devServer) { + onBeforeSetupMiddleware(devServer) { if (!devServer) { throw new Error("webpack-dev-server is not defined"); } - + devServer.app.get("/some/before-path", (req, res) => { res.json({ custom: "response" }); }); @@ -234,11 +234,9 @@ module.exports = { const devServerOptions = { host: "127.0.0.1", port: 8080 }; const devServer = new Server(devServerOptions, compiler); - (async () => { - await devServer.start(); + await devServer.start(); - console.log("Running"); - })(); + console.log("Running"); ``` ```js @@ -273,15 +271,13 @@ module.exports = { const devServerOptions = { host: "127.0.0.1", port: 8080 }; const devServer = new Server(devServerOptions, compiler); - (async () => { - await devServer.start(); + await devServer.start(); - console.log("Running"); + console.log("Running"); - await devServer.stop(); + await devServer.stop(); - console.log("Closed"); - })(); + console.log("Closed"); ``` ```js diff --git a/package-lock.json b/package-lock.json index 153ed5c5a0..df22096ede 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,7 +58,6 @@ "@types/node-forge": "^1.3.1", "@types/sockjs-client": "^1.5.1", "@types/trusted-types": "^2.0.2", - "@typescript-eslint/eslint-plugin": "^8.36.0", "acorn": "^8.14.0", "babel-jest": "^29.5.0", "babel-loader": "^10.0.0", @@ -69,7 +68,7 @@ "css-loader": "^7.1.1", "eslint": "^9.30.1", "eslint-config-prettier": "^10.1.5", - "eslint-config-webpack": "^4.3.0", + "eslint-config-webpack": "^4.3.3", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jest": "^29.0.1", "eslint-plugin-jsdoc": "^51.3.4", @@ -8754,9 +8753,9 @@ } }, "node_modules/eslint-config-webpack": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-webpack/-/eslint-config-webpack-4.3.0.tgz", - "integrity": "sha512-G2mePdT5zOOPS+lYtNKAdLqIgSSRCswirgrWh1+Lk1R2UY2r7q5XTtJbTguOR3ukfFySpYx0vHPTdN8TxpFQtw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/eslint-config-webpack/-/eslint-config-webpack-4.3.3.tgz", + "integrity": "sha512-5MB3a1zXhcHNafPw/Pyi2YkpSSkzWau6QuiwUglC1W9hkkFNbUFNll5XLpVen7UYz3gBQrHMH1yEGTMvh5k1WA==", "dev": true, "license": "MIT", "dependencies": { @@ -8779,6 +8778,7 @@ "eslint-plugin-jsdoc": ">= 50.7.1", "eslint-plugin-n": ">= 17.19.0", "eslint-plugin-prettier": ">= 5.4.1", + "eslint-plugin-react": ">= 7.37.5", "eslint-plugin-unicorn": ">= 59.0.1", "globals": ">= 16.2.0", "prettier": ">= 3.5.3", @@ -8798,6 +8798,9 @@ "eslint-plugin-n": { "optional": true }, + "eslint-plugin-react": { + "optional": true + }, "typescript": { "optional": true }, diff --git a/package.json b/package.json index b804259073..84dfe33dc4 100644 --- a/package.json +++ b/package.json @@ -23,13 +23,13 @@ "scripts": { "fmt:check": "prettier \"{**/*,*}.{js,json,md,yml,css,ts}\" --list-different", "lint:prettier": "prettier --cache --list-different .", - "lint:js": "eslint --cache .", + "lint:code": "eslint --cache .", "lint:types": "tsc --pretty --noEmit", "lint:spelling": "cspell --cache --no-must-find-files --quiet \"**/*.*\"", "lint": "npm-run-all -l -p \"lint:**\"", - "fix:js": "npm run lint:js -- --fix", + "fix:code": "npm run lint:code -- --fix", "fix:prettier": "npm run lint:prettier -- --write", - "fix": "npm-run-all -l fix:js fix:prettier", + "fix": "npm-run-all -l fix:code fix:prettier", "commitlint": "commitlint --from=master", "build:client": "rimraf -g ./client/* && babel client-src/ --out-dir client/ --ignore \"client-src/webpack.config.js\" --ignore \"client-src/modules\" && webpack --config client-src/webpack.config.js", "build:types": "rimraf -g ./types/* && tsc --declaration --emitDeclarationOnly --outDir types && node ./scripts/extend-webpack-types.js && prettier \"types/**/*.ts\" --write && prettier \"types/**/*.ts\" --write", @@ -99,7 +99,7 @@ "css-loader": "^7.1.1", "eslint": "^9.30.1", "eslint-config-prettier": "^10.1.5", - "eslint-config-webpack": "^4.3.0", + "eslint-config-webpack": "^4.3.3", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jest": "^29.0.1", "eslint-plugin-jsdoc": "^51.3.4", diff --git a/scripts/extend-webpack-types.js b/scripts/extend-webpack-types.js index c4f3274149..36a811a933 100644 --- a/scripts/extend-webpack-types.js +++ b/scripts/extend-webpack-types.js @@ -4,7 +4,7 @@ const path = require("node:path"); const fs = require("graceful-fs"); /** - * + * @returns {Promise} */ async function extendTypes() { const typesPath = path.resolve(__dirname, "../types/lib/Server.d.ts"); @@ -26,4 +26,10 @@ declare module "webpack" { await fs.promises.writeFile(typesPath, newContent); } -extendTypes(); +// eslint-disable-next-line unicorn/prefer-top-level-await +Promise.resolve().then( + () => extendTypes(), + (error) => { + throw error; + }, +); diff --git a/scripts/globalSetupTest.js b/scripts/globalSetupTest.js index 0b7195d872..e8ee1c86b3 100644 --- a/scripts/globalSetupTest.js +++ b/scripts/globalSetupTest.js @@ -8,7 +8,7 @@ const ports = require("../test/ports-map"); console.log(`\n Running tests for webpack @${version} \n`); /** - * + * @returns {Promise} */ async function validatePorts() { const samples = []; @@ -33,6 +33,7 @@ async function validatePorts() { } catch (err) { // eslint-disable-next-line no-console console.error(err); + // eslint-disable-next-line n/no-process-exit process.exit(1); } } diff --git a/scripts/prepare-test-for-old-node.js b/scripts/prepare-test-for-old-node.js index b3b5d18f7b..a5ef6dbfa1 100644 --- a/scripts/prepare-test-for-old-node.js +++ b/scripts/prepare-test-for-old-node.js @@ -4,7 +4,7 @@ const fs = require("node:fs"); const path = require("node:path"); /** - * + * @returns {Promise} */ async function setup() { const serverCodePath = path.resolve(__dirname, "../lib/Server.js"); @@ -20,6 +20,7 @@ async function setup() { Promise.resolve() .then(() => setup()) + // eslint-disable-next-line unicorn/prefer-top-level-await .then( () => { // eslint-disable-next-line no-console diff --git a/scripts/setupTest.js b/scripts/setupTest.js index 99a74a59bf..5e0aaeb46d 100644 --- a/scripts/setupTest.js +++ b/scripts/setupTest.js @@ -1,5 +1,7 @@ "use strict"; +/* global jest */ + process.env.CHOKIDAR_USEPOLLING = true; jest.setTimeout(400000); diff --git a/test/cli/basic.test.js b/test/cli/basic.test.js index 3601ad23a2..0aec509162 100644 --- a/test/cli/basic.test.js +++ b/test/cli/basic.test.js @@ -13,7 +13,9 @@ describe("basic", () => { (isMacOS ? it.skip : it)("should generate correct cli flags", async () => { const { exitCode, stdout } = await testBin(["--help"]); + // eslint-disable-next-line jest/no-standalone-expect expect(exitCode).toBe(0); + // eslint-disable-next-line jest/no-standalone-expect expect(stripAnsi(stdout)).toMatchSnapshot(); }); }); @@ -87,7 +89,7 @@ describe("basic", () => { const bits = data.toString(); if (/main.js/.test(bits)) { - expect(cp.pid !== 0).toBe(true); + expect(cp.pid).not.toBe(0); cp.kill("SIGINT"); } @@ -110,7 +112,7 @@ describe("basic", () => { cp.stdout.on("data", () => { if (!killed) { - expect(cp.pid !== 0).toBe(true); + expect(cp.pid).not.toBe(0); cp.kill("SIGINT"); } @@ -144,7 +146,7 @@ describe("basic", () => { const bits = data.toString(); if (/main.js/.test(bits)) { - expect(cp.pid !== 0).toBe(true); + expect(cp.pid).not.toBe(0); cp.stdin.write("hello"); cp.stdin.end("world"); @@ -180,7 +182,7 @@ describe("basic", () => { cp.stdout.on("data", () => { if (!killed) { - expect(cp.pid !== 0).toBe(true); + expect(cp.pid).not.toBe(0); cp.stdin.write("hello"); cp.stdin.end("world"); @@ -322,6 +324,7 @@ describe("basic", () => { expect(stdout).toContain("client/index.js"); }); + // eslint-disable-next-line jest/no-disabled-tests it.skip("should use different random port when multiple instances are started on different processes", async () => { const cliPath = path.resolve( __dirname, @@ -353,7 +356,7 @@ describe("basic", () => { } if (/Compiled successfully/.test(bits)) { - expect(cp.pid !== 0).toBe(true); + expect(cp.pid).not.toBe(0); cp.kill("SIGINT"); } }); @@ -368,7 +371,7 @@ describe("basic", () => { } if (/Compiled successfully/.test(bits)) { - expect(cp.pid !== 0).toBe(true); + expect(cp.pid).not.toBe(0); cp2.kill("SIGINT"); } }); @@ -376,7 +379,7 @@ describe("basic", () => { cp.on("exit", () => { runtime.cp.done = true; if (runtime.cp2.done) { - expect(runtime.cp.port !== runtime.cp2.port).toBe(true); + expect(runtime.cp.port).not.toBe(runtime.cp2.port); } }); @@ -384,7 +387,7 @@ describe("basic", () => { runtime.cp2.done = true; if (runtime.cp.done) { - expect(runtime.cp.port !== runtime.cp2.port).toBe(true); + expect(runtime.cp.port).not.toBe(runtime.cp2.port); } }); }); diff --git a/test/cli/historyApiFallback-option.test.js b/test/cli/historyApiFallback-option.test.js index ed267df8ff..018db0e5b3 100644 --- a/test/cli/historyApiFallback-option.test.js +++ b/test/cli/historyApiFallback-option.test.js @@ -4,7 +4,7 @@ const { normalizeStderr, testBin } = require("../helpers/test-bin"); const port = require("../ports-map")["cli-history-api-fallback"]; describe('"historyApiFallback" CLI option', () => { - it.only('should work using "--history-api-fallback"', async () => { + it('should work using "--history-api-fallback"', async () => { const { exitCode, stderr } = await testBin( ["--port", port, "--history-api-fallback"], { diff --git a/test/cli/host-option.test.js b/test/cli/host-option.test.js index 7e113c91f3..d93dfc8825 100644 --- a/test/cli/host-option.test.js +++ b/test/cli/host-option.test.js @@ -1,9 +1,9 @@ "use strict"; const os = require("node:os"); +const Server = require("../../lib/Server"); const { normalizeStderr, testBin } = require("../helpers/test-bin"); const port = require("../ports-map")["cli-host"]; -const Server = require("../../lib/Server"); const localIPv4 = Server.findIp("v4", false); const localIPv6 = Server.findIp("v6", false); @@ -69,18 +69,6 @@ describe('"host" CLI option', () => { expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); - it('should work using "--host ::1" (IPv6)', async () => { - const { exitCode, stderr } = await testBin([ - "--port", - port, - "--host", - "::1", - ]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - }); - it('should work using "--host "', async () => { const { exitCode, stderr } = await testBin([ "--port", @@ -93,6 +81,7 @@ describe('"host" CLI option', () => { expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); + // eslint-disable-next-line jest/no-disabled-tests it.skip('should work using "--host "', async () => { const { exitCode, stderr } = await testBin([ "--port", @@ -232,8 +221,8 @@ describe('"host" CLI option', () => { }, ], })); - expect(!stderr.includes("172.17.0.1")); - expect(stderr.includes("192.168.1.15")); + expect(stderr).not.toContain("172.17.0.1"); + expect(stderr).toContain("192.168.1.15"); }); it('should work using "--host local-ipv4"', async () => { diff --git a/test/cli/server-option.test.js b/test/cli/server-option.test.js index 4f5d709284..f59af97255 100644 --- a/test/cli/server-option.test.js +++ b/test/cli/server-option.test.js @@ -58,40 +58,15 @@ describe('"server" CLI options', () => { "spdy", ]); + // eslint-disable-next-line jest/no-standalone-expect expect(exitCode).toBe(0); + // eslint-disable-next-line jest/no-standalone-expect expect( normalizeStderr(stderr, { ipv6: true, https: true }), ).toMatchSnapshot(); }, ); - it('should work using "--server-options-key --server-options-pfx --server-options-passphrase webpack-dev-server --server-options-cert "', async () => { - const pfxFile = path.join(httpsCertificateDirectory, "server.pfx"); - const key = path.join(httpsCertificateDirectory, "server.key"); - const cert = path.join(httpsCertificateDirectory, "server.crt"); - const passphrase = "webpack-dev-server"; - - const { exitCode, stderr } = await testBin([ - "--port", - port, - "--server-type", - "https", - "--server-options-key", - key, - "--server-options-pfx", - pfxFile, - "--server-options-passphrase", - passphrase, - "--server-options-cert", - cert, - ]); - - expect(exitCode).toBe(0); - expect( - normalizeStderr(stderr, { ipv6: true, https: true }), - ).toMatchSnapshot(); - }); - it('should work using "--server-options-key --server-options-pfx --server-options-passphrase webpack-dev-server --server-options-cert --server-options-ca "', async () => { const pfxFile = path.join(httpsCertificateDirectory, "server.pfx"); const key = path.join(httpsCertificateDirectory, "server.key"); diff --git a/test/client/clients/SockJSClient.test.js b/test/client/clients/SockJSClient.test.js index 08e8a594c6..ae388b5f20 100644 --- a/test/client/clients/SockJSClient.test.js +++ b/test/client/clients/SockJSClient.test.js @@ -40,8 +40,11 @@ describe("SockJSClient", () => { }); }); - afterAll(() => { + afterAll((done) => { consoleMock.mockRestore(); + server.close(() => { + done(); + }); }); describe("client", () => { @@ -81,10 +84,4 @@ describe("SockJSClient", () => { }, 3000); }); }); - - afterAll((done) => { - server.close(() => { - done(); - }); - }); }); diff --git a/test/e2e/allowed-hosts.test.js b/test/e2e/allowed-hosts.test.js index 3c469f4b1c..163a24f265 100644 --- a/test/e2e/allowed-hosts.test.js +++ b/test/e2e/allowed-hosts.test.js @@ -77,8 +77,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -152,8 +150,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -227,8 +223,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -303,8 +297,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -379,8 +371,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -456,8 +446,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -535,8 +523,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -614,8 +600,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -694,8 +678,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -774,8 +756,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -854,8 +834,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -934,8 +912,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -1017,8 +993,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -1097,8 +1071,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -1177,8 +1149,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("(work) console messages"); expect(pageErrors).toMatchSnapshot("(work) page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -1257,8 +1227,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -1340,8 +1308,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -1420,8 +1386,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -1504,8 +1468,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { proxy.close(); @@ -1584,8 +1546,6 @@ describe("allowed hosts", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("(work) console messages"); expect(pageErrors).toMatchSnapshot("(work) page errors"); - } catch (error) { - throw error; } finally { proxy.close(); diff --git a/test/e2e/api.test.js b/test/e2e/api.test.js index b86c19d144..f8a536af49 100644 --- a/test/e2e/api.test.js +++ b/test/e2e/api.test.js @@ -100,8 +100,6 @@ describe("API", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -140,8 +138,6 @@ describe("API", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await new Promise((resolve) => { @@ -213,8 +209,6 @@ describe("API", () => { consoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -249,8 +243,6 @@ describe("API", () => { firstConsoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(firstPageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await server.stop(); } @@ -279,8 +271,6 @@ describe("API", () => { secondConsoleMessages.map((message) => message.text()), ).toMatchSnapshot("console messages"); expect(secondPageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -391,7 +381,7 @@ describe("API", () => { const basePort = process.env.WEBPACK_DEV_SERVER_TEST_BASE_PORT || 30000; process.env.WEBPACK_DEV_SERVER_BASE_PORT = basePort; - return (Array.isArray(n) ? n : [...new Array(n)]).reduce( + return (Array.isArray(n) ? n : Array.from({ length: n })).reduce( (p, _, i) => p.then( () => @@ -488,7 +478,7 @@ describe("API", () => { const retryKey = `retry_${expect.getState().currentTestName}`; // Get current retry count or initialize to 0 - global[retryKey] = global[retryKey] || 0; + global[retryKey] ||= 0; global[retryKey] += 1; if (global[retryKey] < maxRetries) { @@ -564,7 +554,7 @@ describe("API", () => { const retryKey = `retry_${expect.getState().currentTestName}`; // Get current retry count or initialize to 0 - global[retryKey] = global[retryKey] || 0; + global[retryKey] ||= 0; global[retryKey] += 1; if (global[retryKey] < maxRetries) { @@ -640,7 +630,7 @@ describe("API", () => { const retryKey = `retry_${expect.getState().currentTestName}`; // Get current retry count or initialize to 0 - global[retryKey] = global[retryKey] || 0; + global[retryKey] ||= 0; global[retryKey] += 1; if (global[retryKey] < maxRetries) { @@ -717,7 +707,7 @@ describe("API", () => { const retryKey = `retry_${expect.getState().currentTestName}`; // Get current retry count or initialize to 0 - global[retryKey] = global[retryKey] || 0; + global[retryKey] ||= 0; global[retryKey] += 1; if (global[retryKey] < maxRetries) { @@ -796,7 +786,7 @@ describe("API", () => { const retryKey = `retry_${expect.getState().currentTestName}`; // Get current retry count or initialize to 0 - global[retryKey] = global[retryKey] || 0; + global[retryKey] ||= 0; global[retryKey] += 1; if (global[retryKey] < maxRetries) { @@ -816,7 +806,7 @@ describe("API", () => { const retryKey = `retry_${expect.getState().currentTestName}`; // Get current retry count or initialize to 0 - global[retryKey] = global[retryKey] || 0; + global[retryKey] ||= 0; global[retryKey] += 1; if (global[retryKey] < maxRetries) { @@ -869,13 +859,17 @@ describe("API", () => { const compiler = webpack(config); const server = new Server(options, compiler); + let isValidHost = true; + for (const test of tests) { const headers = { host: test }; if (!server.isValidHost(headers, "host")) { - throw new Error("Validation didn't pass"); + isValidHost = false; } } + + expect(isValidHost).toBe(true); }); it('should allow URLs with scheme for checking origin when the "option.client.webSocketURL" is object', async () => { @@ -966,7 +960,7 @@ describe("API", () => { const retryKey = `retry_${expect.getState().currentTestName}`; // Get current retry count or initialize to 0 - global[retryKey] = global[retryKey] || 0; + global[retryKey] ||= 0; global[retryKey] += 1; if (global[retryKey] < maxRetries) { @@ -986,7 +980,7 @@ describe("API", () => { const retryKey = `retry_${expect.getState().currentTestName}`; // Get current retry count or initialize to 0 - global[retryKey] = global[retryKey] || 0; + global[retryKey] ||= 0; global[retryKey] += 1; if (global[retryKey] < maxRetries) { diff --git a/test/e2e/client-reconnect.test.js b/test/e2e/client-reconnect.test.js index 345bb63cf8..eff831783d 100644 --- a/test/e2e/client-reconnect.test.js +++ b/test/e2e/client-reconnect.test.js @@ -47,8 +47,6 @@ describe("client.reconnect option", () => { try { expect(response.status()).toMatchSnapshot("response status"); - } catch (error) { - throw error; } finally { await server.stop(); } @@ -113,22 +111,19 @@ describe("client.reconnect option", () => { try { expect(response.status()).toMatchSnapshot("response status"); - } catch (error) { - throw error; } finally { await server.stop(); } // Can't wait to check for unlimited times so wait only for couple retries - await new Promise((resolve) => + await new Promise((resolve) => { setTimeout( () => { resolve(); }, - 1000 * 2 ** 3, - ), - ); + ); + }); expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( "console messages", @@ -178,22 +173,19 @@ describe("client.reconnect option", () => { try { expect(response.status()).toMatchSnapshot("response status"); - } catch (error) { - throw error; } finally { await server.stop(); } // Can't wait to check for unlimited times so wait only for couple retries - await new Promise((resolve) => + await new Promise((resolve) => { setTimeout( () => { resolve(); }, - 1000 * 2 ** 3, - ), - ); + ); + }); expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( "console messages", diff --git a/test/e2e/cross-origin-request.test.js b/test/e2e/cross-origin-request.test.js index ff8b8959a1..d003024928 100644 --- a/test/e2e/cross-origin-request.test.js +++ b/test/e2e/cross-origin-request.test.js @@ -55,8 +55,6 @@ describe("cross-origin requests", () => { const response = await scriptTagRequest; expect(response.status()).toBe(403); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -111,8 +109,6 @@ describe("cross-origin requests", () => { const response = await scriptTagRequest; expect(response.status()).toBe(200); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -164,8 +160,6 @@ describe("cross-origin requests", () => { const response = await scriptTagRequest; expect(response.status()).toBe(200); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -217,8 +211,6 @@ describe("cross-origin requests", () => { const response = await scriptTagRequest; expect(response.status()).toBe(200); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/e2e/entry.test.js b/test/e2e/entry.test.js index 3917c94a47..311d87c333 100644 --- a/test/e2e/entry.test.js +++ b/test/e2e/entry.test.js @@ -63,8 +63,6 @@ describe("entry", () => { "console messages", ); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -102,8 +100,6 @@ describe("entry", () => { "console messages", ); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -146,8 +142,6 @@ describe("entry", () => { "console messages", ); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -185,8 +179,6 @@ describe("entry", () => { "console messages", ); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -196,7 +188,10 @@ describe("entry", () => { it("should work with dynamic async entry", async () => { const compiler = webpack({ ...config, - entry: () => new Promise((resolve) => resolve([entryFirst])), + entry: () => + new Promise((resolve) => { + resolve([entryFirst]); + }), }); const devServerOptions = { port, @@ -227,8 +222,6 @@ describe("entry", () => { "console messages", ); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -278,8 +271,6 @@ describe("entry", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -329,8 +320,6 @@ describe("entry", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -378,8 +367,6 @@ describe("entry", () => { expect(consoleMessages).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -425,8 +412,6 @@ describe("entry", () => { "console messages", ); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/e2e/host.test.js b/test/e2e/host.test.js index c7be637a66..fe79392ca4 100644 --- a/test/e2e/host.test.js +++ b/test/e2e/host.test.js @@ -139,8 +139,6 @@ describe("host", () => { ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -215,8 +213,6 @@ describe("host", () => { ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -295,8 +291,6 @@ describe("host", () => { ).toMatchSnapshot("console messages"); expect(pageErrors).toMatchSnapshot("page errors"); - } catch (error) { - throw error; } finally { delete process.env.WEBPACK_DEV_SERVER_BASE_PORT; @@ -307,6 +301,7 @@ describe("host", () => { } // TODO need test on error + // eslint-disable-next-line jest/no-commented-out-tests // it(`should throw an error on invalid host`, async () => { // const compiler = webpack(config); // const server = new Server({ port, host: "unknown.unknown" }, compiler); diff --git a/test/e2e/hot-and-live-reload.test.js b/test/e2e/hot-and-live-reload.test.js index ba2c6ee06a..32e1f9dcb3 100644 --- a/test/e2e/hot-and-live-reload.test.js +++ b/test/e2e/hot-and-live-reload.test.js @@ -332,6 +332,7 @@ describe("hot and live reload", () => { ? mode.options.webSocketServer : "default"; + // eslint-disable-next-line no-loop-func it(`${mode.title} (${webSocketServerTitle})`, async () => { const webpackOptions = { ...reloadConfig, ...mode.webpackOptions }; const compiler = webpack(webpackOptions); @@ -367,9 +368,8 @@ describe("hot and live reload", () => { let received = false; let errored = false; - ws.on("error", (error) => { - errored = - !webSocketServerLaunched && /404/.test(error) ? true : true; + ws.on("error", (_error) => { + errored = true; ws.close(); }); diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js index 8607da2053..b96a0bcfb6 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -227,6 +227,7 @@ describe("web socket server URL", () => { const ipc = path.join(pipePrefix, pipeName); const ipcServer = await new Promise((resolve, reject) => { + // eslint-disable-next-line new-cap const server = net.Server(); server.on("error", (error) => { diff --git a/test/e2e/module-federation.test.js b/test/e2e/module-federation.test.js index c544f0d61c..f1fa63144f 100644 --- a/test/e2e/module-federation.test.js +++ b/test/e2e/module-federation.test.js @@ -6,9 +6,9 @@ const Server = require("../../lib/Server"); const simpleConfig = require("../fixtures/module-federation-config/webpack.config"); const multiConfig = require("../fixtures/module-federation-config/webpack.multi.config"); const objectEntryConfig = require("../fixtures/module-federation-config/webpack.object-entry.config"); +const pluginConfig = require("../fixtures/module-federation-config/webpack.plugin"); const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map")["module-federation"]; -const pluginConfig = require("../fixtures/module-federation-config/webpack.plugin"); describe("Module federation", () => { describe("should work with simple multi-entry config", () => { diff --git a/test/e2e/options-middleware.test.js b/test/e2e/options-middleware.test.js index fcaec60b64..1bc05cd64b 100644 --- a/test/e2e/options-middleware.test.js +++ b/test/e2e/options-middleware.test.js @@ -93,8 +93,6 @@ describe("handle options-request correctly", () => { ); expect(responseStatus.sort()).toEqual([200, 204]); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/e2e/overlay.test.js b/test/e2e/overlay.test.js index ef2bf5ac10..e9a3140bdc 100644 --- a/test/e2e/overlay.test.js +++ b/test/e2e/overlay.test.js @@ -63,7 +63,10 @@ class WarningPlugin { } } -const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); +const delay = (ms) => + new Promise((resolve) => { + setTimeout(resolve, ms); + }); let prettier; let prettierHTML; @@ -118,7 +121,7 @@ describe("overlay", () => { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("overlay html"); + ).toMatchSnapshot("overlay html"); } finally { await browser.close(); await server.stop(); @@ -265,7 +268,7 @@ describe("overlay", () => { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("overlay html"); + ).toMatchSnapshot("overlay html"); } finally { await browser.close(); await server.stop(); @@ -588,8 +591,6 @@ describe("overlay", () => { ).toMatchSnapshot("page html after close"); fs.writeFileSync(pathToFile, originalCode); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -678,7 +679,7 @@ describe("overlay", () => { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("page html"); + ).toMatchSnapshot("page html"); } finally { await browser.close(); await server.stop(); @@ -764,8 +765,6 @@ describe("overlay", () => { const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); expect(overlayHandle).toBeNull(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -869,7 +868,7 @@ describe("overlay", () => { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("overlay html"); + ).toMatchSnapshot("overlay html"); } finally { await browser.close(); await server.stop(); @@ -1101,8 +1100,6 @@ describe("overlay", () => { const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); expect(overlayHandle).toBeNull(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1269,7 +1266,7 @@ describe("overlay", () => { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("overlay html"); + ).toMatchSnapshot("overlay html"); } finally { await browser.close(); await server.stop(); @@ -1622,7 +1619,7 @@ describe("overlay", () => { parser: "html", plugins: [prettierHTML, prettierCSS], }), - ).toMatchSnapshot("overlay html"); + ).toMatchSnapshot("overlay html"); } finally { await browser.close(); await server.stop(); @@ -1684,8 +1681,6 @@ describe("overlay", () => { plugins: [prettierHTML, prettierCSS], }), ).toMatchSnapshot("overlay html"); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); @@ -1774,8 +1769,6 @@ describe("overlay", () => { const overlayHandle = await page.$("#webpack-dev-server-client-overlay"); expect(overlayHandle).toBeNull(); - } catch (error) { - throw error; } finally { await browser.close(); await server.stop(); diff --git a/test/e2e/server.test.js b/test/e2e/server.test.js index 457e4c8558..582e531873 100644 --- a/test/e2e/server.test.js +++ b/test/e2e/server.test.js @@ -858,89 +858,6 @@ describe("server option", () => { }); }); - describe("ca, pfx, key and cert are buffer", () => { - let compiler; - let server; - let createServerSpy; - let page; - let browser; - let pageErrors; - let consoleMessages; - - beforeEach(async () => { - compiler = webpack(config); - - createServerSpy = jest.spyOn(https, "createServer"); - - server = new Server( - { - static: { - directory: staticDirectory, - watch: false, - }, - server: { - type: "https", - options: { - ca: fs.readFileSync( - path.join(httpsCertificateDirectory, "ca.pem"), - ), - pfx: fs.readFileSync( - path.join(httpsCertificateDirectory, "server.pfx"), - ), - key: fs.readFileSync( - path.join(httpsCertificateDirectory, "server.key"), - ), - cert: fs.readFileSync( - path.join(httpsCertificateDirectory, "server.crt"), - ), - passphrase: "webpack-dev-server", - }, - }, - port, - }, - compiler, - ); - - await server.start(); - - ({ page, browser } = await runBrowser()); - - pageErrors = []; - consoleMessages = []; - }); - - afterEach(async () => { - createServerSpy.mockRestore(); - - await browser.close(); - await server.stop(); - }); - - it("should handle GET request to index route (/)", async () => { - page - .on("console", (message) => { - consoleMessages.push(message); - }) - .on("pageerror", (error) => { - pageErrors.push(error); - }); - - const response = await page.goto(`https://localhost:${port}/`, { - waitUntil: "networkidle0", - }); - - expect( - normalizeOptions(createServerSpy.mock.calls[0][0]), - ).toMatchSnapshot("https options"); - expect(response.status()).toMatchSnapshot("response status"); - expect(await response.text()).toMatchSnapshot("response text"); - expect( - consoleMessages.map((message) => message.text()), - ).toMatchSnapshot("console messages"); - expect(pageErrors).toMatchSnapshot("page errors"); - }); - }); - describe("ca, pfx, key and cert are buffer, key and pfx are objects", () => { let compiler; let server; diff --git a/test/e2e/static-directory.test.js b/test/e2e/static-directory.test.js index 415026ebe0..a4f2b02002 100644 --- a/test/e2e/static-directory.test.js +++ b/test/e2e/static-directory.test.js @@ -103,7 +103,8 @@ describe("static.directory option", () => { it("watches folder recursively", (done) => { // chokidar emitted a change, // meaning it watched the file correctly - server.staticWatchers[0].on("change", () => { + server.staticWatchers[0].on("change", (filepath) => { + expect(typeof filepath).toBe("string"); done(); }); @@ -120,7 +121,9 @@ describe("static.directory option", () => { // chokidar emitted a change, // meaning it watched the file correctly - server.staticWatchers[0].on("change", () => { + server.staticWatchers[0].on("change", (filepath) => { + expect(typeof filepath).toBe("string"); + fs.unlinkSync(filePath); done(); @@ -513,7 +516,10 @@ describe("static.directory option", () => { }, port, }, - done, + (error) => { + expect(error).toBeUndefined(); + done(error); + }, ); }); @@ -527,7 +533,10 @@ describe("static.directory option", () => { }, port, }, - done, + (error) => { + expect(error).toBeUndefined(); + done(error); + }, ); }); @@ -541,7 +550,10 @@ describe("static.directory option", () => { }, port, }, - done, + (error) => { + expect(error).toBeUndefined(); + done(error); + }, ); }); diff --git a/test/e2e/stats.test.js b/test/e2e/stats.test.js index 297c31a321..70f3017b12 100644 --- a/test/e2e/stats.test.js +++ b/test/e2e/stats.test.js @@ -138,5 +138,5 @@ describe("stats", () => { await server.stop(); } }); - } + } }); diff --git a/test/e2e/web-socket-communication.test.js b/test/e2e/web-socket-communication.test.js index 8afb7ac0e5..8af3b3678a 100644 --- a/test/e2e/web-socket-communication.test.js +++ b/test/e2e/web-socket-communication.test.js @@ -8,8 +8,6 @@ const config = require("../fixtures/client-config/webpack.config"); const runBrowser = require("../helpers/run-browser"); const port = require("../ports-map")["web-socket-communication"]; -jest.setTimeout(60000); - describe("web socket communication", () => { const webSocketServers = ["ws", "sockjs"]; @@ -174,6 +172,9 @@ describe("web socket communication", () => { server.webSocketServer.heartbeatInterval = 100; + let opened = false; + let received = false; + await new Promise((resolve, reject) => { const ws = new WebSocket(`ws://localhost:${devServerOptions.port}/ws`, { headers: { @@ -182,9 +183,6 @@ describe("web socket communication", () => { }, }); - let opened = false; - let received = false; - ws.on("open", () => { opened = true; }); @@ -212,6 +210,9 @@ describe("web socket communication", () => { }); }); + expect(opened).toBe(true); + expect(received).toBe(true); + await server.stop(); }); }); diff --git a/test/helpers/conditional-test.js b/test/helpers/conditional-test.js index f3486ed6a3..0dbc6af2fb 100644 --- a/test/helpers/conditional-test.js +++ b/test/helpers/conditional-test.js @@ -1,11 +1,14 @@ "use strict"; +/* global test */ + const isWindows = process.platform === "win32"; function skipTestOnWindows(reason) { if (isWindows) { test.skip(reason, () => {}); } + return isWindows; } diff --git a/test/helpers/run-browser.js b/test/helpers/run-browser.js index 85207539aa..b0fd6f86a0 100644 --- a/test/helpers/run-browser.js +++ b/test/helpers/run-browser.js @@ -3,17 +3,24 @@ const puppeteer = require("puppeteer"); const { puppeteerArgs } = require("./puppeteer-constants"); +/** @typedef {import('puppeteer').Browser} Browser */ +/** @typedef {import('puppeteer').Page} Page */ +/** @typedef {import('puppeteer').Device} Device */ + /** * @typedef {object} RunBrowserResult - * @property {import('puppeteer').Page} page - * @property {import('puppeteer').Browser} browser + * @property {Page} page page + * @property {Browser} browser browser */ - - -function runPage(browser, config) { +/** + * @param {Browser} browser browser + * @param {Device} device config + * @returns {Promise} page + */ +function runPage(browser, device) { /** - * @type {import('puppeteer').Page} + * @type {Page} */ let page; @@ -23,7 +30,7 @@ function runPage(browser, config) { height: 500, }, userAgent: "", - ...config, + ...device, }; return Promise.resolve() @@ -56,10 +63,10 @@ function runPage(browser, config) { } /** - * @param {Parameters[0]} config + * @param {Device} device device * @returns {Promise} */ -function runBrowser(config) { +function runBrowser(device) { return new Promise((resolve, reject) => { /** * @type {import('puppeteer').Page} @@ -81,7 +88,7 @@ function runBrowser(config) { .then((launchedBrowser) => { browser = launchedBrowser; - return runPage(launchedBrowser, config); + return runPage(launchedBrowser, device); }) .then((newPage) => { page = newPage; diff --git a/test/server/open-option.test.js b/test/server/open-option.test.js index 27e29ca815..fea4bf65a6 100644 --- a/test/server/open-option.test.js +++ b/test/server/open-option.test.js @@ -41,6 +41,7 @@ describe('"open" option', () => { open.mockClear(); }); + // eslint-disable-next-line jest/no-focused-tests it.only("should work with unspecified host", async () => { const server = new Server( { @@ -881,7 +882,7 @@ describe('"open" option', () => { loggerWarnSpy.mockRestore(); }); - it("should log warning when can't open with object with the 'app' option with arguments", async () => { + it("should log warning when can't open with object with the 'app' option with arguments #2", async () => { open.mockRejectedValue(undefined); const loggerWarnSpy = jest.fn(); diff --git a/test/validate-options.test.js b/test/validate-options.test.js index d8f9ccfa47..b92f9be1fd 100644 --- a/test/validate-options.test.js +++ b/test/validate-options.test.js @@ -555,8 +555,6 @@ const tests = { }, }; -jest.setTimeout(20000); - describe("options", () => { let consoleMock; diff --git a/types/bin/webpack-dev-server.d.ts b/types/bin/webpack-dev-server.d.ts index d3ec8a3a55..a84d4ae0f5 100644 --- a/types/bin/webpack-dev-server.d.ts +++ b/types/bin/webpack-dev-server.d.ts @@ -23,5 +23,5 @@ export type CliOption = { /** * preprocessor */ - preprocess: Function; + preprocess: () => void; }; diff --git a/types/lib/Server.d.ts b/types/lib/Server.d.ts index 41b09a245e..47dfba4c62 100644 --- a/types/lib/Server.d.ts +++ b/types/lib/Server.d.ts @@ -1123,58 +1123,60 @@ declare class Server< }; }; /** - * @param {string} URL - * @returns {boolean} + * @private + * @returns {StatsOptions} default stats options + */ + private static get DEFAULT_STATS(); + /** + * @param {string} URL url + * @returns {boolean} true when URL is absolute, otherwise false */ static isAbsoluteURL(URL: string): boolean; /** - * @param {string} gatewayOrFamily or family - * @param {boolean} [isInternal] ip should be internal - * @returns {string | undefined} + * @param {string} gatewayOrFamily gateway or family + * @param {boolean=} isInternal ip should be internal + * @returns {string | undefined} resolved IP */ static findIp( gatewayOrFamily: string, - isInternal?: boolean, + isInternal?: boolean | undefined, ): string | undefined; /** - * @param {"v4" | "v6"} family - * @returns {Promise} + * @param {"v4" | "v6"} family family + * @returns {Promise} internal API */ static internalIP(family: "v4" | "v6"): Promise; /** - * @param {"v4" | "v6"} family - * @returns {string | undefined} + * @param {"v4" | "v6"} family family + * @returns {string | undefined} internal IP */ static internalIPSync(family: "v4" | "v6"): string | undefined; /** - * @param {Host} hostname - * @returns {Promise} + * @param {Host} hostname hostname + * @returns {Promise} resolved hostname */ static getHostname(hostname: Host): Promise; /** - * @param {Port} port - * @param {string} host - * @returns {Promise} + * @param {Port} port port + * @param {string} host host + * @returns {Promise} free port */ static getFreePort(port: Port, host: string): Promise; /** - * @returns {string} + * @returns {string} path to cache dir */ static findCacheDir(): string; /** * @private - * @param {Compiler} compiler - * @returns bool + * @param {Compiler} compiler compiler + * @returns {boolean} true when target is `web`, otherwise false */ private static isWebTarget; /** - * @param {Configuration} options - * @param {Compiler | MultiCompiler} compiler + * @param {Configuration} options options + * @param {Compiler | MultiCompiler} compiler compiler */ - constructor( - options: Configuration | undefined, - compiler: Compiler | MultiCompiler, - ); + constructor(options: Configuration, compiler: Compiler | MultiCompiler); compiler: import("webpack").Compiler | import("webpack").MultiCompiler; /** * @type {ReturnType} @@ -1187,7 +1189,7 @@ declare class Server< staticWatchers: FSWatcher[]; /** * @private - * @type {{ name: string | symbol, listener: (...args: any[]) => void}[] }} + * @type {{ name: string | symbol, listener: (...args: EXPECTED_ANY[]) => void}[] }} */ private listeners; /** @@ -1206,12 +1208,12 @@ declare class Server< private currentHash; /** * @private - * @param {Compiler} compiler + * @param {Compiler} compiler compiler */ private addAdditionalEntries; /** * @private - * @returns {Compiler["options"]} + * @returns {Compiler["options"]} compiler options */ private getCompilerOptions; /** @@ -1221,13 +1223,13 @@ declare class Server< private normalizeOptions; /** * @private - * @returns {string} + * @returns {string} client transport */ private getClientTransport; /** * @template T * @private - * @returns {T} + * @returns {T} server transport */ private getServerTransport; /** @@ -1235,7 +1237,7 @@ declare class Server< */ getClientEntry(): string; /** - * @returns {string | void} + * @returns {string | void} client hot entry */ getClientHotEntry(): string | void; /** @@ -1257,8 +1259,8 @@ declare class Server< app: A | undefined; /** * @private - * @param {Stats | MultiStats} statsObj - * @returns {StatsCompilation} + * @param {Stats | MultiStats} statsObj stats + * @returns {StatsCompilation} stats of compilation */ private getStats; /** @@ -1316,7 +1318,7 @@ declare class Server< webSocketServer: WebSocketServerImplementation | undefined | null; /** * @private - * @param {string} defaultOpenTarget + * @param {string} defaultOpenTarget default open target * @returns {Promise} */ private openBrowser; @@ -1331,8 +1333,8 @@ declare class Server< */ private bonjour; /** - * @param callback * @private + * @param {() => void} callback callback * @returns {void} */ private stopBonjour; @@ -1343,79 +1345,83 @@ declare class Server< private logStatus; /** * @private - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req request + * @param {Response} res response + * @param {NextFunction} next next function */ private setHeaders; /** * @private - * @param {string} value - * @returns {boolean} + * @param {string} value value + * @returns {boolean} true when host allowed, otherwise false */ private isHostAllowed; /** * @private - * @param {{ [key: string]: string | undefined }} headers - * @param {string} headerToCheck - * @param {boolean} validateHost - * @returns {boolean} + * @param {{ [key: string]: string | undefined }} headers headers + * @param {string} headerToCheck header to check + * @param {boolean} validateHost need to validate host + * @returns {boolean} true when host is valid, otherwise false */ private isValidHost; /** * @private - * @param {{ [key: string]: string | undefined }} headers - * @returns {boolean} + * @param {{ [key: string]: string | undefined }} headers headers + * @returns {boolean} true when is same origin, otherwise false */ private isSameOrigin; /** - * @param {ClientConnection[]} clients - * @param {string} type - * @param {any} [data] - * @param {any} [params] + * @param {ClientConnection[]} clients clients + * @param {string} type type + * @param {EXPECTED_ANY=} data data + * @param {EXPECTED_ANY=} params params */ sendMessage( clients: ClientConnection[], type: string, - data?: any, - params?: any, + data?: EXPECTED_ANY | undefined, + params?: EXPECTED_ANY | undefined, ): void; /** * @private - * @param {ClientConnection[]} clients - * @param {StatsCompilation} stats - * @param {boolean} [force] + * @param {ClientConnection[]} clients clients + * @param {StatsCompilation} stats stats + * @param {boolean=} force force */ private sendStats; /** - * @param {string | string[]} watchPath - * @param {WatchOptions} [watchOptions] + * @param {string | string[]} watchPath watch path + * @param {WatchOptions=} watchOptions watch options */ - watchFiles(watchPath: string | string[], watchOptions?: WatchOptions): void; + watchFiles( + watchPath: string | string[], + watchOptions?: WatchOptions | undefined, + ): void; /** - * @param {import("webpack-dev-middleware").Callback} [callback] + * @param {import("webpack-dev-middleware").Callback=} callback callback */ - invalidate(callback?: import("webpack-dev-middleware").Callback): void; + invalidate( + callback?: import("webpack-dev-middleware").Callback | undefined, + ): void; /** * @returns {Promise} */ start(): Promise; /** - * @param {(err?: Error) => void} [callback] + * @param {((err?: Error) => void)=} callback callback */ - startCallback(callback?: (err?: Error) => void): void; + startCallback(callback?: ((err?: Error) => void) | undefined): void; /** * @returns {Promise} */ stop(): Promise; /** - * @param {(err?: Error) => void} [callback] + * @param {((err?: Error) => void)=} callback callback */ - stopCallback(callback?: (err?: Error) => void): void; + stopCallback(callback?: ((err?: Error) => void) | undefined): void; } declare namespace Server { export { - DEFAULT_STATS, Schema, Compiler, MultiCompiler, @@ -1447,6 +1453,7 @@ declare namespace Server { ExpressErrorRequestHandler, ExpressRequest, ExpressResponse, + EXPECTED_ANY, NextFunction, SimpleHandleFunction, NextHandleFunction, @@ -1483,12 +1490,10 @@ declare namespace Server { Middleware, BasicServer, Configuration, + FunctionReturning, BasicApplication, }; } -declare class DEFAULT_STATS { - private constructor(); -} type Schema = import("schema-utils/declarations/validate").Schema; type Compiler = import("webpack").Compiler; type MultiCompiler = import("webpack").MultiCompiler; @@ -1521,7 +1526,8 @@ type ExpressRequestHandler = import("express").RequestHandler; type ExpressErrorRequestHandler = import("express").ErrorRequestHandler; type ExpressRequest = import("express").Request; type ExpressResponse = import("express").Response; -type NextFunction = (err?: any) => void; +type EXPECTED_ANY = any; +type NextFunction = (err?: EXPECTED_ANY) => void; type SimpleHandleFunction = (req: IncomingMessage, res: ServerResponse) => void; type NextHandleFunction = ( req: IncomingMessage, @@ -1529,7 +1535,7 @@ type NextHandleFunction = ( next: NextFunction, ) => void; type ErrorHandleFunction = ( - err: any, + err: EXPECTED_ANY, req: IncomingMessage, res: ServerResponse, next: NextFunction, @@ -1562,9 +1568,15 @@ type DevMiddlewareContext< type Host = "local-ip" | "local-ipv4" | "local-ipv6" | string; type Port = number | string | "auto"; type WatchFiles = { + /** + * paths + */ paths: string | string[]; + /** + * options + */ options?: - | (import("chokidar").WatchOptions & { + | (WatchOptions & { aggregateTimeout?: number; ignored?: WatchOptions["ignored"]; poll?: number | boolean; @@ -1572,21 +1584,34 @@ type WatchFiles = { | undefined; }; type Static = { + /** + * directory + */ directory?: string | undefined; - publicPath?: string | string[] | undefined; - serveIndex?: boolean | import("serve-index").Options | undefined; - staticOptions?: - | import("serve-static").ServeStaticOptions< - import("http").ServerResponse - > - | undefined; + /** + * public path + */ + publicPath?: (string | string[]) | undefined; + /** + * serve index + */ + serveIndex?: (boolean | ServeIndexOptions) | undefined; + /** + * static options + */ + staticOptions?: ServeStaticOptions | undefined; + /** + * watch and watch options + */ watch?: - | boolean - | (import("chokidar").WatchOptions & { - aggregateTimeout?: number; - ignored?: WatchOptions["ignored"]; - poll?: number | boolean; - }) + | ( + | boolean + | (WatchOptions & { + aggregateTimeout?: number; + ignored?: WatchOptions["ignored"]; + poll?: number | boolean; + }) + ) | undefined; }; type NormalizedStatic = { @@ -1608,7 +1633,7 @@ type ServerType< | "spdy" | "http2" | string - | ((arg0: ServerOptions, arg1: A) => S); + | ((serverOptions: ServerOptions, application: A) => S); type ServerConfiguration< A extends BasicApplication = import("express").Application, S extends BasicServer = import("http").Server< @@ -1616,12 +1641,26 @@ type ServerConfiguration< typeof import("http").ServerResponse >, > = { + /** + * type + */ type?: ServerType | undefined; + /** + * options + */ options?: ServerOptions | undefined; }; type WebSocketServerConfiguration = { - type?: string | Function | undefined; - options?: Record | undefined; + /** + * type + */ + type?: + | ("sockjs" | "ws" | string | (() => WebSocketServerConfiguration)) + | undefined; + /** + * options + */ + options?: Record | undefined; }; type ClientConnection = ( | import("ws").WebSocket @@ -1666,36 +1705,79 @@ type OpenApp = { arguments?: string[] | undefined; }; type Open = { - app?: string | string[] | OpenApp | undefined; - target?: string | string[] | undefined; + app?: (string | string[] | OpenApp) | undefined; + /** + * target + */ + target?: (string | string[]) | undefined; }; type NormalizedOpen = { target: string; options: import("open").Options; }; type WebSocketURL = { + /** + * hostname + */ hostname?: string | undefined; + /** + * password + */ password?: string | undefined; + /** + * pathname + */ pathname?: string | undefined; - port?: string | number | undefined; + /** + * port + */ + port?: (number | string) | undefined; + /** + * protocol + */ protocol?: string | undefined; + /** + * username + */ username?: string | undefined; }; type OverlayMessageOptions = boolean | ((error: Error) => void); type ClientConfiguration = { - logging?: "none" | "error" | "warn" | "info" | "log" | "verbose" | undefined; + /** + * logging + */ + logging?: + | ("log" | "info" | "warn" | "error" | "none" | "verbose") + | undefined; + /** + * overlay + */ overlay?: - | boolean - | { - warnings?: OverlayMessageOptions; - errors?: OverlayMessageOptions; - runtimeErrors?: OverlayMessageOptions; - } + | ( + | boolean + | { + warnings?: OverlayMessageOptions; + errors?: OverlayMessageOptions; + runtimeErrors?: OverlayMessageOptions; + } + ) | undefined; + /** + * progress + */ progress?: boolean | undefined; - reconnect?: number | boolean | undefined; - webSocketTransport?: string | undefined; - webSocketURL?: string | WebSocketURL | undefined; + /** + * reconnect + */ + reconnect?: (boolean | number) | undefined; + /** + * web socket transport + */ + webSocketTransport?: ("ws" | "sockjs" | string) | undefined; + /** + * web socket URL + */ + webSocketURL?: (string | WebSocketURL) | undefined; }; type Headers = | Array<{ @@ -1722,81 +1804,65 @@ type Configuration< typeof import("http").ServerResponse >, > = { - ipc?: string | boolean | undefined; - host?: string | undefined; + ipc?: (boolean | string) | undefined; + host?: Host | undefined; port?: Port | undefined; - hot?: boolean | "only" | undefined; + hot?: (boolean | "only") | undefined; liveReload?: boolean | undefined; - devMiddleware?: - | DevMiddlewareOptions< - import("express").Request< - import("express-serve-static-core").ParamsDictionary, - any, - any, - qs.ParsedQs, - Record - >, - import("express").Response> - > - | undefined; + devMiddleware?: DevMiddlewareOptions | undefined; compress?: boolean | undefined; - allowedHosts?: string | string[] | undefined; - historyApiFallback?: - | boolean - | import("connect-history-api-fallback").Options - | undefined; - bonjour?: - | boolean - | Record - | import("bonjour-service").Service - | undefined; + allowedHosts?: ("auto" | "all" | string | string[]) | undefined; + historyApiFallback?: (boolean | ConnectHistoryApiFallbackOptions) | undefined; + bonjour?: (boolean | Record | BonjourOptions) | undefined; watchFiles?: - | string - | string[] - | WatchFiles - | (string | WatchFiles)[] + | (string | string[] | WatchFiles | Array) | undefined; - static?: string | boolean | Static | (string | Static)[] | undefined; - server?: ServerType | ServerConfiguration | undefined; + static?: (boolean | string | Static | Array) | undefined; + server?: (ServerType | ServerConfiguration) | undefined; app?: (() => Promise) | undefined; - webSocketServer?: string | boolean | WebSocketServerConfiguration | undefined; + webSocketServer?: + | (boolean | "sockjs" | "ws" | string | WebSocketServerConfiguration) + | undefined; proxy?: ProxyConfigArray | undefined; - open?: string | boolean | Open | (string | Open)[] | undefined; + open?: (boolean | string | Open | Array) | undefined; setupExitSignals?: boolean | undefined; - client?: boolean | ClientConfiguration | undefined; + client?: (boolean | ClientConfiguration) | undefined; headers?: - | Headers - | (( - req: Request, - res: Response, - context: DevMiddlewareContext | undefined, - ) => Headers) + | ( + | Headers + | (( + req: Request, + res: Response, + context: DevMiddlewareContext | undefined, + ) => Headers) + ) | undefined; onListening?: ((devServer: Server) => void) | undefined; setupMiddlewares?: | ((middlewares: Middleware[], devServer: Server) => Middleware[]) | undefined; }; +type FunctionReturning = () => T; type BasicApplication = { use: typeof useFn; }; /** * @overload - * @param {NextHandleFunction} fn - * @returns {BasicApplication} + * @param {NextHandleFunction} fn function + * @returns {BasicApplication} application */ declare function useFn(fn: NextHandleFunction): BasicApplication; /** * @overload - * @param {HandleFunction} fn - * @returns {BasicApplication} + * @param {HandleFunction} fn function + * @returns {BasicApplication} application */ declare function useFn(fn: HandleFunction): BasicApplication; /** * @overload - * @param {string} route - * @param {NextHandleFunction} fn - * @returns {BasicApplication} + * @param {string} route route + * @param {NextHandleFunction} fn function + * @returns {BasicApplication} application */ declare function useFn(route: string, fn: NextHandleFunction): BasicApplication; diff --git a/types/lib/getPort.d.ts b/types/lib/getPort.d.ts index b1e91d14ca..677eb97671 100644 --- a/types/lib/getPort.d.ts +++ b/types/lib/getPort.d.ts @@ -1,8 +1,8 @@ export = getPorts; /** - * @param {number} basePort - * @param {string=} host - * @returns {Promise} + * @param {number} basePort base port + * @param {string=} host host + * @returns {Promise} resolved port */ declare function getPorts( basePort: number, diff --git a/types/lib/servers/BaseServer.d.ts b/types/lib/servers/BaseServer.d.ts index 87aedf8ba9..07d29fb4b5 100644 --- a/types/lib/servers/BaseServer.d.ts +++ b/types/lib/servers/BaseServer.d.ts @@ -1,7 +1,7 @@ export = BaseServer; declare class BaseServer { /** - * @param {import("../Server")} server + * @param {import("../Server")} server server */ constructor(server: import("../Server")); /** @type {import("../Server")} */ From d568e91ccd5168bab1cc4cfeadf5d709668f39e6 Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Mon, 14 Jul 2025 19:44:39 +0300 Subject: [PATCH 3/8] chore: initial work --- eslint.config.js | 22 ---------------------- eslint.config.mjs | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 22 deletions(-) delete mode 100644 eslint.config.js create mode 100644 eslint.config.mjs diff --git a/eslint.config.js b/eslint.config.js deleted file mode 100644 index 149a56f73b..0000000000 --- a/eslint.config.js +++ /dev/null @@ -1,22 +0,0 @@ -import { defineConfig } from "eslint/config"; -import config from "eslint-config-webpack"; - -export default defineConfig([ - { - ignores: ["client/**/*", "types/**/*", "examples/**/main.js", "examples/client/trusted-types-overlay/app.js"] - }, - { - extends: [config], - }, - { - files: ["test/**/*"], - rules: { - "jsdoc/require-jsdoc": "off", - "jsdoc/require-returns": "off", - "jsdoc/require-param-description": "off", - "jsdoc/require-param-type": "off", - "jsdoc/require-property-description": "off", - "jsdoc/require-returns-description": "off", - } - } -]); diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..0fb905f626 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,37 @@ +import { defineConfig, globalIgnores } from "eslint/config"; +import config from "eslint-config-webpack"; +import configs from "eslint-config-webpack/configs.js"; + +export default defineConfig([ + globalIgnores([ + "client/**/*", + "client-src/**/*", + "examples/**/*", + "examples/client/trusted-types-overlay/app.js", + ]), + { + extends: [config], + rules: { + // TODO fix me + "prefer-destructuring": "off", + + "jsdoc/require-property-description": "off", + }, + }, + { + files: ["test/**/*"], + extends: [configs["browser/recommended"]], + rules: { + // TODO improve me in the default eslint configuration + "import/extensions": "off", + "jsdoc/check-tag-names": "off", + + "jsdoc/require-jsdoc": "off", + "jsdoc/require-returns": "off", + "jsdoc/require-param-description": "off", + "jsdoc/require-param-type": "off", + "jsdoc/require-property-description": "off", + "jsdoc/require-returns-description": "off", + }, + }, +]); From 30aaab2f94320f7396b821acbd967e71e4898f1f Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Mon, 14 Jul 2025 20:00:06 +0300 Subject: [PATCH 4/8] test: fix --- lib/Server.js | 1 - test/cli/__snapshots__/host-option.test.js.snap.webpack5 | 6 ------ test/cli/host-option.test.js | 3 ++- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index dab20b9728..bd4348a667 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -410,7 +410,6 @@ class Server { let host; const networks = Object.values(os.networkInterfaces()) - .flatMap((networks) => networks ?? []) .filter((network) => { if (!network || !network.address) { diff --git a/test/cli/__snapshots__/host-option.test.js.snap.webpack5 b/test/cli/__snapshots__/host-option.test.js.snap.webpack5 index 54a5e6b310..7b4ae825d1 100644 --- a/test/cli/__snapshots__/host-option.test.js.snap.webpack5 +++ b/test/cli/__snapshots__/host-option.test.js.snap.webpack5 @@ -14,12 +14,6 @@ exports[`"host" CLI option should work using "--host ::1" (IPv6): stderr 1`] = ` [webpack-dev-server] Content not from webpack is served from '/public' directory" `; -exports[`"host" CLI option should work using "--host ::1" (IPv6): stderr 2`] = ` -" [webpack-dev-server] Project is running at: - Loopback: http://localhost:/, http://:/, http://[]:/ - [webpack-dev-server] Content not from webpack is served from '/public' directory" -`; - exports[`"host" CLI option should work using "--host ": stderr 1`] = ` " [webpack-dev-server] Project is running at: [webpack-dev-server] On Your Network (IPv4): http://:/ diff --git a/test/cli/host-option.test.js b/test/cli/host-option.test.js index d93dfc8825..dfa65ee92b 100644 --- a/test/cli/host-option.test.js +++ b/test/cli/host-option.test.js @@ -106,7 +106,8 @@ describe('"host" CLI option', () => { expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); }); - it('should work using "--host local-ip" take the first network found', async () => { + // eslint-disable-next-line jest/no-disabled-tests + it.skip('should work using "--host local-ip" take the first network found', async () => { const { exitCode, stderr } = await testBin([ "--port", port, From eaf018bc2226b70cda4b98482e79e9c360b8fa72 Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Tue, 15 Jul 2025 16:08:23 +0300 Subject: [PATCH 5/8] refactor: code --- DOCUMENTATION-v4.md | 10 +- README.md | 6 +- client-src/clients/SockJSClient.js | 28 +++--- client-src/clients/WebSocketClient.js | 24 +++-- client-src/index.js | 130 ++++++++++++------------ client-src/modules/logger/tapable.js | 4 + client-src/overlay.js | 134 ++++++++++++++----------- client-src/progress.js | 13 ++- client-src/socket.js | 15 +-- client-src/utils/log.js | 2 +- client-src/utils/sendMessage.js | 8 +- eslint.config.mjs | 28 ++---- examples/on-listening/README.md | 2 +- lib/Server.js | 4 +- package-lock.json | 8 +- package.json | 2 +- test/cli/basic.test.js | 4 +- test/client/index.test.js | 8 +- test/client/socket-helper.test.js | 6 +- test/e2e/ipc.test.js | 6 +- test/e2e/web-socket-server-url.test.js | 2 +- test/helpers/conditional-test.js | 4 + test/helpers/normalize-options.js | 3 +- test/helpers/run-browser.js | 2 +- test/helpers/test-server.js | 60 +++++------ test/server/proxy-option.test.js | 6 +- 26 files changed, 267 insertions(+), 252 deletions(-) diff --git a/DOCUMENTATION-v4.md b/DOCUMENTATION-v4.md index 3e34dba4f9..467a6ab8c9 100644 --- a/DOCUMENTATION-v4.md +++ b/DOCUMENTATION-v4.md @@ -1087,7 +1087,7 @@ internally within the server. module.exports = { // ... devServer: { - onAfterSetupMiddleware (devServer) { + onAfterSetupMiddleware(devServer) { if (!devServer) { throw new Error("webpack-dev-server is not defined"); } @@ -1118,7 +1118,7 @@ example: module.exports = { // ... devServer: { - onBeforeSetupMiddleware (devServer) { + onBeforeSetupMiddleware(devServer) { if (!devServer) { throw new Error("webpack-dev-server is not defined"); } @@ -1147,12 +1147,12 @@ Provides the ability to execute a custom function when webpack-dev-server starts module.exports = { // ... devServer: { - onListening (devServer) { + onListening(devServer) { if (!devServer) { throw new Error("webpack-dev-server is not defined"); } - const {port} = devServer.server.address(); + const { port } = devServer.server.address(); console.log("Listening on port:", port); }, }, @@ -1394,7 +1394,7 @@ module.exports = { proxy: { "/api": { target: "http://localhost:3000", - bypass (req, res, proxyOptions) { + bypass(req, res, proxyOptions) { if (req.headers.accept.includes("html")) { console.log("Skipping proxy for browser request."); return "/index.html"; diff --git a/README.md b/README.md index d0d49ae267..7314c0e1b2 100644 --- a/README.md +++ b/README.md @@ -229,7 +229,7 @@ If you use TypeScript in the webpack config, you'll need to properly type `devSe ```ts /// -import { type Configuration } from "webpack"; +import { type Configuration } from "webpack"; // Your logic ``` @@ -237,8 +237,8 @@ import { type Configuration } from "webpack"; Or you can import the type from `webpack-dev-server`, i.e. ```ts -import { type Configuration } from "webpack"; -import { type Configuration as DevServerConfiguration } from "webpack-dev-server"; +import { type Configuration } from "webpack"; +import { type Configuration as DevServerConfiguration } from "webpack-dev-server"; const devServer: DevServerConfiguration = {}; const config: Configuration = { devServer }; diff --git a/client-src/clients/SockJSClient.js b/client-src/clients/SockJSClient.js index 4efcafd0c4..aa0c057fec 100644 --- a/client-src/clients/SockJSClient.js +++ b/client-src/clients/SockJSClient.js @@ -1,9 +1,11 @@ import SockJS from "../modules/sockjs-client/index.js"; import { log } from "../utils/log.js"; +/** @typedef {import("../index").EXPECTED_ANY} EXPECTED_ANY */ + export default class SockJSClient { /** - * @param {string} url + * @param {string} url url */ constructor(url) { // SockJS requires `http` and `https` protocols @@ -12,7 +14,7 @@ export default class SockJSClient { ); this.sock.onerror = /** - * @param {Error} error + * @param {Error} error error */ (error) => { log.error(error); @@ -20,30 +22,30 @@ export default class SockJSClient { } /** - * @param {(...args: any[]) => void} f + * @param {(...args: EXPECTED_ANY[]) => void} fn function */ - onOpen(f) { - this.sock.onopen = f; + onOpen(fn) { + this.sock.onopen = fn; } /** - * @param {(...args: any[]) => void} f + * @param {(...args: EXPECTED_ANY[]) => void} fn function */ - onClose(f) { - this.sock.onclose = f; + onClose(fn) { + this.sock.onclose = fn; } // call f with the message string as the first argument /** - * @param {(...args: any[]) => void} f + * @param {(...args: EXPECTED_ANY[]) => void} fn function */ - onMessage(f) { + onMessage(fn) { this.sock.onmessage = /** - * @param {Error & { data: string }} e + * @param {Error & { data: string }} err error */ - (e) => { - f(e.data); + (err) => { + fn(err.data); }; } } diff --git a/client-src/clients/WebSocketClient.js b/client-src/clients/WebSocketClient.js index cdbd94f360..8aa8bb85c4 100644 --- a/client-src/clients/WebSocketClient.js +++ b/client-src/clients/WebSocketClient.js @@ -1,8 +1,10 @@ import { log } from "../utils/log.js"; +/** @typedef {import("../index").EXPECTED_ANY} EXPECTED_ANY */ + export default class WebSocketClient { /** - * @param {string} url + * @param {string} url url to connect */ constructor(url) { this.client = new WebSocket(url); @@ -12,26 +14,26 @@ export default class WebSocketClient { } /** - * @param {(...args: any[]) => void} f + * @param {(...args: EXPECTED_ANY[]) => void} fn function */ - onOpen(f) { - this.client.onopen = f; + onOpen(fn) { + this.client.onopen = fn; } /** - * @param {(...args: any[]) => void} f + * @param {(...args: EXPECTED_ANY[]) => void} fn function */ - onClose(f) { - this.client.onclose = f; + onClose(fn) { + this.client.onclose = fn; } // call f with the message string as the first argument /** - * @param {(...args: any[]) => void} f + * @param {(...args: EXPECTED_ANY[]) => void} fn function */ - onMessage(f) { - this.client.onmessage = (e) => { - f(e.data); + onMessage(fn) { + this.client.onmessage = (err) => { + fn(err.data); }; } } diff --git a/client-src/index.js b/client-src/index.js index f4e1597500..930fc4ba48 100644 --- a/client-src/index.js +++ b/client-src/index.js @@ -1,56 +1,60 @@ /* global __resourceQuery, __webpack_hash__ */ /// -import webpackHotLog from "webpack/hot/log.js"; import hotEmitter from "webpack/hot/emitter.js"; +import webpackHotLog from "webpack/hot/log.js"; +import { createOverlay, formatProblem } from "./overlay.js"; +import { defineProgressElement, isProgressSupported } from "./progress.js"; import socket from "./socket.js"; -import { formatProblem, createOverlay } from "./overlay.js"; import { log, setLogLevel } from "./utils/log.js"; import sendMessage from "./utils/sendMessage.js"; -import { isProgressSupported, defineProgressElement } from "./progress.js"; + +// eslint-disable-next-line jsdoc/no-restricted-syntax +/** @typedef {any} EXPECTED_ANY */ /** - * @typedef {Object} OverlayOptions - * @property {boolean | (error: Error) => boolean} [warnings] - * @property {boolean | (error: Error) => boolean} [errors] - * @property {boolean | (error: Error) => boolean} [runtimeErrors] - * @property {string} [trustedTypesPolicyName] + * @typedef {object} OverlayOptions + * @property {(boolean | (error: Error) => boolean)=} warnings warnings + * @property {(boolean | (error: Error) => boolean)=} errors errors + * @property {(boolean | (error: Error) => boolean)=} runtimeErrors runtime errors + * @property {string=} trustedTypesPolicyName trusted types policy name */ /** - * @typedef {Object} Options - * @property {boolean} hot - * @property {boolean} liveReload - * @property {boolean} progress - * @property {boolean | OverlayOptions} overlay - * @property {string} [logging] - * @property {number} [reconnect] + * @typedef {object} Options + * @property {boolean} hot true when hot enabled, otherwise false + * @property {boolean} liveReload true when live reload enabled, otherwise false + * @property {boolean} progress true when need to show progress, otherwise false + * @property {boolean | OverlayOptions} overlay overlay options + * @property {string=} logging logging level + * @property {number=} reconnect count of allowed reconnection */ /** - * @typedef {Object} Status - * @property {boolean} isUnloading - * @property {string} currentHash - * @property {string} [previousHash] + * @typedef {object} Status + * @property {boolean} isUnloading true when unloaded, otherwise false + * @property {string} currentHash current hash + * @property {string=} previousHash previous hash */ /** - * @param {boolean | { warnings?: boolean | string; errors?: boolean | string; runtimeErrors?: boolean | string; }} overlayOptions + * @param {boolean | { warnings?: boolean | string, errors?: boolean | string, runtimeErrors?: boolean | string }} overlayOptions overlay options */ const decodeOverlayOptions = (overlayOptions) => { if (typeof overlayOptions === "object") { - ["warnings", "errors", "runtimeErrors"].forEach((property) => { + for (const property of ["warnings", "errors", "runtimeErrors"]) { if (typeof overlayOptions[property] === "string") { const overlayFilterFunctionString = decodeURIComponent( overlayOptions[property], ); + // eslint-disable-next-line no-new-func overlayOptions[property] = new Function( "message", `var callback = ${overlayFilterFunctionString} return callback(message)`, ); } - }); + } } }; @@ -63,7 +67,7 @@ const status = { }; /** - * @returns {string} + * @returns {string} current script source */ const getCurrentScriptSource = () => { // `document.currentScript` is the most accurate way to find the current script, @@ -91,8 +95,8 @@ const getCurrentScriptSource = () => { }; /** - * @param {string} resourceQuery - * @returns {{ [key: string]: string | boolean }} + * @param {string} resourceQuery resource query + * @returns {{ [key: string]: string | boolean }} parsed URL */ const parseURL = (resourceQuery) => { /** @type {{ [key: string]: string }} */ @@ -117,7 +121,7 @@ const parseURL = (resourceQuery) => { // is to allow parsing of path-relative or protocol-relative URLs, // and will have no effect if `scriptSource` is a fully valid URL. scriptSourceURL = new URL(scriptSource, self.location.href); - } catch (error) { + } catch (_err) { // URL parsing failed, do nothing. // We will still proceed to see if we can recover using `resourceQuery` } @@ -166,8 +170,8 @@ if (parsedResourceQuery.progress === "true") { if (parsedResourceQuery.overlay) { try { options.overlay = JSON.parse(parsedResourceQuery.overlay); - } catch (e) { - log.error("Error parsing overlay options from resource query:", e); + } catch (err) { + log.error("Error parsing overlay options from resource query:", err); } // Fill in default "true" params for partially-specified objects. @@ -193,7 +197,7 @@ if (typeof parsedResourceQuery.reconnect !== "undefined") { } /** - * @param {string} level + * @param {string} level level */ const setAllLogLevel = (level) => { // This is needed because the HMR logger operate separately from dev server logger @@ -248,8 +252,8 @@ const overlay = : { send: () => {} }; /** - * @param {Options} options - * @param {Status} currentStatus + * @param {Options} options options + * @param {Status} currentStatus current status */ const reloadApp = ({ hot, liveReload }, currentStatus) => { if (currentStatus.isUnloading) { @@ -265,8 +269,8 @@ const reloadApp = ({ hot, liveReload }, currentStatus) => { } /** - * @param {Window} rootWindow - * @param {number} intervalId + * @param {Window} rootWindow root window + * @param {number} intervalId interval id */ function applyReload(rootWindow, intervalId) { clearInterval(intervalId); @@ -321,13 +325,11 @@ const ansiRegex = new RegExp( ); /** - * * Strip [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) from a string. * Adapted from code originally released by Sindre Sorhus * Licensed the MIT License - * - * @param {string} string - * @return {string} + * @param {string} string string + * @returns {string} string without ansi */ const stripAnsi = (string) => { if (typeof string !== "string") { @@ -363,7 +365,7 @@ const onSocketMessage = { sendMessage("Invalid"); }, /** - * @param {string} hash + * @param {string} hash hash */ hash(hash) { status.previousHash = status.currentHash; @@ -371,7 +373,7 @@ const onSocketMessage = { }, logging: setAllLogLevel, /** - * @param {boolean} value + * @param {boolean} value overlay value */ overlay(value) { if (typeof document === "undefined") { @@ -382,7 +384,7 @@ const onSocketMessage = { decodeOverlayOptions(options.overlay); }, /** - * @param {number} value + * @param {number} value reconnect value */ reconnect(value) { if (parsedResourceQuery.reconnect === "false") { @@ -392,13 +394,13 @@ const onSocketMessage = { options.reconnect = value; }, /** - * @param {boolean} value + * @param {boolean} value progress value */ progress(value) { options.progress = value; }, /** - * @param {{ pluginName?: string, percent: number, msg: string }} data + * @param {{ pluginName?: string, percent: number, msg: string }} data date with progress */ "progress-update": function progressUpdate(data) { if (options.progress) { @@ -409,17 +411,15 @@ const onSocketMessage = { ); } - if (isProgressSupported()) { - if (typeof options.progress === "string") { - let progress = document.querySelector("wds-progress"); - if (!progress) { - defineProgressElement(); - progress = document.createElement("wds-progress"); - document.body.appendChild(progress); - } - progress.setAttribute("progress", data.percent); - progress.setAttribute("type", options.progress); + if (isProgressSupported() && typeof options.progress === "string") { + let progress = document.querySelector("wds-progress"); + if (!progress) { + defineProgressElement(); + progress = document.createElement("wds-progress"); + document.body.appendChild(progress); } + progress.setAttribute("progress", data.percent); + progress.setAttribute("type", options.progress); } sendMessage("Progress", data); @@ -443,7 +443,7 @@ const onSocketMessage = { reloadApp(options, status); }, /** - * @param {string} file + * @param {string} file changed file */ "static-changed": function staticChanged(file) { log.info( @@ -455,8 +455,8 @@ const onSocketMessage = { self.location.reload(); }, /** - * @param {Error[]} warnings - * @param {any} params + * @param {Error[]} warnings warnings + * @param {{ preventReloading: boolean }=} params extra params */ warnings(warnings, params) { log.warn("Warnings while compiling."); @@ -500,7 +500,7 @@ const onSocketMessage = { reloadApp(options, status); }, /** - * @param {Error[]} errors + * @param {Error[]} errors errors */ errors(errors) { log.error("Errors while compiling. Reload prevented."); @@ -538,7 +538,7 @@ const onSocketMessage = { } }, /** - * @param {Error} error + * @param {Error} error error */ error(error) { log.error(error); @@ -555,13 +555,13 @@ const onSocketMessage = { }; /** - * @param {{ protocol?: string, auth?: string, hostname?: string, port?: string, pathname?: string, search?: string, hash?: string, slashes?: boolean }} objURL - * @returns {string} + * @param {{ protocol?: string, auth?: string, hostname?: string, port?: string, pathname?: string, search?: string, hash?: string, slashes?: boolean }} objURL object URL + * @returns {string} formatted url */ const formatURL = (objURL) => { let protocol = objURL.protocol || ""; - if (protocol && protocol.substr(-1) !== ":") { + if (protocol && protocol.slice(-1) !== ":") { protocol += ":"; } @@ -614,8 +614,8 @@ const formatURL = (objURL) => { pathname = pathname.replace( /[?#]/g, /** - * @param {string} match - * @returns {string} + * @param {string} match matched string + * @returns {string} encoded URI component */ (match) => encodeURIComponent(match), ); @@ -625,8 +625,8 @@ const formatURL = (objURL) => { }; /** - * @param {URL & { fromCurrentScript?: boolean }} parsedURL - * @returns {string} + * @param {URL & { fromCurrentScript?: boolean }} parsedURL parsed URL + * @returns {string} socket URL */ const createSocketURL = (parsedURL) => { let { hostname } = parsedURL; @@ -720,4 +720,4 @@ const socketURL = createSocketURL(parsedResourceQuery); socket(socketURL, onSocketMessage, options.reconnect); -export { getCurrentScriptSource, parseURL, createSocketURL }; +export { createSocketURL, getCurrentScriptSource, parseURL }; diff --git a/client-src/modules/logger/tapable.js b/client-src/modules/logger/tapable.js index 9cc27e00a2..abd59d5edd 100644 --- a/client-src/modules/logger/tapable.js +++ b/client-src/modules/logger/tapable.js @@ -1,3 +1,7 @@ +/** + * @returns {SyncBailHook} mocked sync bail hook + * @constructor + */ function SyncBailHook() { return { call() {}, diff --git a/client-src/overlay.js b/client-src/overlay.js index 0aa13e4648..79aaefc0dd 100644 --- a/client-src/overlay.js +++ b/client-src/overlay.js @@ -3,6 +3,8 @@ import ansiHTML from "ansi-html-community"; +/** @typedef {import("./index").EXPECTED_ANY} EXPECTED_ANY */ + /** * @type {(input: string, position: number) => string} */ @@ -15,10 +17,10 @@ const getCodePoint = String.prototype.codePointAt 0x10000; /** - * @param {string} macroText - * @param {RegExp} macroRegExp - * @param {(input: string) => string} macroReplacer - * @returns {string} + * @param {string} macroText macro text + * @param {RegExp} macroRegExp macro reg exp + * @param {(input: string) => string} macroReplacer macro replacer + * @returns {string} result */ const replaceUsingRegExp = (macroText, macroRegExp, macroReplacer) => { macroRegExp.lastIndex = 0; @@ -29,10 +31,7 @@ const replaceUsingRegExp = (macroText, macroRegExp, macroReplacer) => { let replaceLastIndex = 0; do { if (replaceLastIndex !== replaceMatch.index) { - replaceResult += macroText.substring( - replaceLastIndex, - replaceMatch.index, - ); + replaceResult += macroText.slice(replaceLastIndex, replaceMatch.index); } const replaceInput = replaceMatch[0]; replaceResult += macroReplacer(replaceInput); @@ -40,7 +39,7 @@ const replaceUsingRegExp = (macroText, macroRegExp, macroReplacer) => { } while ((replaceMatch = macroRegExp.exec(macroText))); if (replaceLastIndex !== macroText.length) { - replaceResult += macroText.substring(replaceLastIndex); + replaceResult += macroText.slice(replaceLastIndex); } } else { replaceResult = macroText; @@ -58,7 +57,7 @@ const references = { /** * @param {string} text text - * @returns {string} + * @returns {string} encoded text */ function encode(text) { if (!text) { @@ -77,36 +76,43 @@ function encode(text) { } /** - * @typedef {Object} StateDefinitions - * @property {{[event: string]: { target: string; actions?: Array }}} [on] + * @typedef {object} StateDefinitions + * @property {{ [event: string]: { target: string; actions?: Array } }=} on event + */ + +/** @typedef {Record} Context */ + +/** @typedef {{ type: string } & Record} Event */ + +/** + * @typedef {object} Options + * @property {{ [state: string]: StateDefinitions }} states states + * @property {Context} context context + * @property {string} initial initial */ /** - * @typedef {Object} Options - * @property {{[state: string]: StateDefinitions}} states - * @property {object} context; - * @property {string} initial + * @typedef {object} Implementation + * @property {{ [actionName: string]: (ctx: Context, event: Event) => EXPECTED_ANY }} actions actions */ /** - * @typedef {Object} Implementation - * @property {{[actionName: string]: (ctx: object, event: any) => object}} actions + * @typedef {{ send: (event: Event) => void }} StateMachine */ /** * A simplified `createMachine` from `@xstate/fsm` with the following differences: - * - * - the returned machine is technically a "service". No `interpret(machine).start()` is needed. - * - the state definition only support `on` and target must be declared with { target: 'nextState', actions: [] } explicitly. - * - event passed to `send` must be an object with `type` property. - * - actions implementation will be [assign action](https://xstate.js.org/docs/guides/context.html#assign-action) if you return any value. - * Do not return anything if you just want to invoke side effect. + * - the returned machine is technically a "service". No `interpret(machine).start()` is needed. + * - the state definition only support `on` and target must be declared with { target: 'nextState', actions: [] } explicitly. + * - event passed to `send` must be an object with `type` property. + * - actions implementation will be [assign action](https://xstate.js.org/docs/guides/context.html#assign-action) if you return any value. + * Do not return anything if you just want to invoke side effect. * * The goal of this custom function is to avoid installing the entire `'xstate/fsm'` package, while enabling modeling using * state machine. You can copy the first parameter into the editor at https://stately.ai/viz to visualize the state machine. - * - * @param {Options} options - * @param {Implementation} implementation + * @param {Options} options options + * @param {Implementation} implementation implementation + * @returns {StateMachine} state machine */ function createMachine({ states, context, initial }, { actions }) { let currentState = initial; @@ -140,20 +146,21 @@ function createMachine({ states, context, initial }, { actions }) { } /** - * @typedef {Object} ShowOverlayData - * @property {'warning' | 'error'} level - * @property {Array} messages - * @property {'build' | 'runtime'} messageSource + * @typedef {object} ShowOverlayData + * @property {'warning' | 'error'} level level + * @property {Array} messages messages + * @property {'build' | 'runtime'} messageSource message source */ /** - * @typedef {Object} CreateOverlayMachineOptions - * @property {(data: ShowOverlayData) => void} showOverlay - * @property {() => void} hideOverlay + * @typedef {object} CreateOverlayMachineOptions + * @property {(data: ShowOverlayData) => void} showOverlay show overlay + * @property {() => void} hideOverlay hide overlay */ /** - * @param {CreateOverlayMachineOptions} options + * @param {CreateOverlayMachineOptions} options options + * @returns {StateMachine} state machine */ const createOverlayMachine = (options) => { const { hideOverlay, showOverlay } = options; @@ -240,12 +247,12 @@ const createOverlayMachine = (options) => { }; /** - * - * @param {Error} error + * @param {Error} error error + * @returns {string[]} stack */ const parseErrorToStacks = (error) => { if (!error || !(error instanceof Error)) { - throw new Error(`parseErrorToStacks expects Error object`); + throw new Error("parseErrorToStacks expects Error object"); } if (typeof error.stack === "string") { return error.stack @@ -261,7 +268,8 @@ const parseErrorToStacks = (error) => { */ /** - * @param {ErrorCallback} callback + * @param {ErrorCallback} callback callback + * @returns {() => void} cleanup */ const listenToRuntimeError = (callback) => { window.addEventListener("error", callback); @@ -278,7 +286,8 @@ const listenToRuntimeError = (callback) => { */ /** - * @param {UnhandledRejectionCallback} callback + * @param {UnhandledRejectionCallback} callback callback + * @returns {() => void} cleanup */ const listenToUnhandledRejection = (callback) => { window.addEventListener("unhandledrejection", callback); @@ -380,9 +389,9 @@ const colors = { ansiHTML.setColors(colors); /** - * @param {string} type - * @param {string | { file?: string, moduleName?: string, loc?: string, message?: string; stack?: string[] }} item - * @returns {{ header: string, body: string }} + * @param {string} type type + * @param {string | { file?: string, moduleName?: string, loc?: string, message?: string; stack?: string[] }} item item + * @returns {{ header: string, body: string }} formatted problem */ const formatProblem = (type, item) => { let header = type === "warning" ? "WARNING" : "ERROR"; @@ -421,14 +430,14 @@ const formatProblem = (type, item) => { }; /** - * @typedef {Object} CreateOverlayOptions - * @property {string | null} trustedTypesPolicyName - * @property {boolean | (error: Error) => void} [catchRuntimeError] + * @typedef {object} CreateOverlayOptions + * @property {string | null} trustedTypesPolicyName trusted types policy name + * @property {(boolean | (error: Error) => void)=} catchRuntimeError runtime error catcher */ /** - * - * @param {CreateOverlayOptions} options + * @param {CreateOverlayOptions} options options + * @returns {StateMachine} overlay */ const createOverlay = (options) => { /** @type {HTMLIFrameElement | null | undefined} */ @@ -443,9 +452,8 @@ const createOverlay = (options) => { let overlayTrustedTypesPolicy; /** - * - * @param {HTMLElement} element - * @param {CSSStyleDeclaration} style + * @param {HTMLElement} element element + * @param {CSSStyleDeclaration} style style */ function applyStyle(element, style) { Object.keys(style).forEach((prop) => { @@ -454,7 +462,7 @@ const createOverlay = (options) => { } /** - * @param {string | null} trustedTypesPolicyName + * @param {string | null} trustedTypesPolicyName trusted types police name */ function createContainer(trustedTypesPolicyName) { // Enable Trusted Types if they are available in the current browser. @@ -501,6 +509,7 @@ const createOverlay = (options) => { closeButtonElement.innerText = "×"; closeButtonElement.ariaLabel = "Dismiss"; closeButtonElement.addEventListener("click", () => { + // eslint-disable-next-line no-use-before-define overlayService.send({ type: "DISMISS" }); }); @@ -527,8 +536,8 @@ const createOverlay = (options) => { } /** - * @param {(element: HTMLDivElement) => void} callback - * @param {string | null} trustedTypesPolicyName + * @param {(element: HTMLDivElement) => void} callback callback + * @param {string | null} trustedTypesPolicyName trusted types policy name */ function ensureOverlayExists(callback, trustedTypesPolicyName) { if (containerElement) { @@ -551,6 +560,9 @@ const createOverlay = (options) => { } // Successful compilation. + /** + * @returns {void} + */ function hide() { if (!iframeContainerElement) { return; @@ -565,10 +577,10 @@ const createOverlay = (options) => { // Compilation with errors (e.g. syntax error or missing modules). /** - * @param {string} type - * @param {Array} messages - * @param {string | null} trustedTypesPolicyName - * @param {'build' | 'runtime'} messageSource + * @param {string} type type + * @param {Array} messages messages + * @param {string | null} trustedTypesPolicyName trusted types policy name + * @param {'build' | 'runtime'} messageSource message source */ function show(type, messages, trustedTypesPolicyName, messageSource) { ensureOverlayExists(() => { @@ -629,8 +641,8 @@ const createOverlay = (options) => { if (options.catchRuntimeError) { /** - * @param {Error | undefined} error - * @param {string} fallbackMessage + * @param {Error | undefined} error error + * @param {string} fallbackMessage fallback message */ const handleError = (error, fallbackMessage) => { const errorObject = @@ -684,4 +696,4 @@ const createOverlay = (options) => { return overlayService; }; -export { formatProblem, createOverlay }; +export { createOverlay, formatProblem }; diff --git a/client-src/progress.js b/client-src/progress.js index 02e74ef781..711d91c0f5 100644 --- a/client-src/progress.js +++ b/client-src/progress.js @@ -1,7 +1,15 @@ +/** + * @returns {boolean} true when custom elements supported, otherwise false + */ export function isProgressSupported() { - return "customElements" in self && !!HTMLElement.prototype.attachShadow; + return ( + "customElements" in self && Boolean(HTMLElement.prototype.attachShadow) + ); } +/** + * @returns {void} + */ export function defineProgressElement() { if (customElements.get("wds-progress")) { return; @@ -28,7 +36,8 @@ export function defineProgressElement() { : WebpackDevServerProgress.#linearTemplate(); this.shadowRoot.innerHTML = innerHTML; - this.initialProgress = Number(this.getAttribute("progress")) ?? 0; + const progressValue = this.getAttribute("progress"); + this.initialProgress = progressValue ? Number(progressValue) : 0; this.#update(this.initialProgress); } diff --git a/client-src/socket.js b/client-src/socket.js index f0e8c3c22d..4d74c160ae 100644 --- a/client-src/socket.js +++ b/client-src/socket.js @@ -3,6 +3,8 @@ import WebSocketClient from "./clients/WebSocketClient.js"; import { log } from "./utils/log.js"; +/** @typedef {import("../index").EXPECTED_ANY} EXPECTED_ANY */ + // this WebsocketClient is here as a default fallback, in case the client is not injected const Client = typeof __webpack_dev_server_client__ !== "undefined" @@ -16,16 +18,17 @@ let maxRetries = 10; // Initialized client is exported so external consumers can utilize the same instance // It is mutable to enforce singleton +// eslint-disable-next-line import/no-mutable-exports export let client = null; let timeout; /** - * @param {string} url - * @param {{ [handler: string]: (data?: any, params?: any) => any }} handlers - * @param {number} [reconnect] + * @param {string} url url + * @param {{ [handler: string]: (data?: EXPECTED_ANY, params?: EXPECTED_ANY) => EXPECTED_ANY }} handlers handlers + * @param {number=} reconnect count of reconnections */ -const socket = function initSocket(url, handlers, reconnect) { +function socket(url, handlers, reconnect) { client = new Client(url); client.onOpen(() => { @@ -66,7 +69,7 @@ const socket = function initSocket(url, handlers, reconnect) { client.onMessage( /** - * @param {any} data + * @param {EXPECTED_ANY} data data */ (data) => { const message = JSON.parse(data); @@ -76,6 +79,6 @@ const socket = function initSocket(url, handlers, reconnect) { } }, ); -}; +} export default socket; diff --git a/client-src/utils/log.js b/client-src/utils/log.js index aecf104a17..3823fe2e1d 100644 --- a/client-src/utils/log.js +++ b/client-src/utils/log.js @@ -7,7 +7,7 @@ const defaultLevel = "info"; // options new options, merge with old options /** - * @param {false | true | "none" | "error" | "warn" | "info" | "log" | "verbose"} level + * @param {false | true | "none" | "error" | "warn" | "info" | "log" | "verbose"} level level * @returns {void} */ function setLogLevel(level) { diff --git a/client-src/utils/sendMessage.js b/client-src/utils/sendMessage.js index 46f0914861..3da67069e0 100644 --- a/client-src/utils/sendMessage.js +++ b/client-src/utils/sendMessage.js @@ -1,9 +1,11 @@ -/* global __resourceQuery WorkerGlobalScope */ +/* global WorkerGlobalScope */ + +/** @typedef {import("../index").EXPECTED_ANY} EXPECTED_ANY */ // Send messages to the outside, so plugins can consume it. /** - * @param {string} type - * @param {any} [data] + * @param {string} type type + * @param {EXPECTED_ANY=} data data */ function sendMsg(type, data) { if ( diff --git a/eslint.config.mjs b/eslint.config.mjs index 0fb905f626..52ac3be3ee 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -3,35 +3,23 @@ import config from "eslint-config-webpack"; import configs from "eslint-config-webpack/configs.js"; export default defineConfig([ - globalIgnores([ - "client/**/*", - "client-src/**/*", - "examples/**/*", - "examples/client/trusted-types-overlay/app.js", - ]), + globalIgnores(["client/**/*", "examples/**/*"]), { extends: [config], + ignores: ["client-src/**/*", "!client-src/webpack.config.js"], rules: { // TODO fix me "prefer-destructuring": "off", - "jsdoc/require-property-description": "off", }, }, + { + files: ["client-src/**/*"], + ignores: ["client-src/webpack.config.js"], + extends: [configs["browser-outdated-recommended"]], + }, { files: ["test/**/*"], - extends: [configs["browser/recommended"]], - rules: { - // TODO improve me in the default eslint configuration - "import/extensions": "off", - "jsdoc/check-tag-names": "off", - - "jsdoc/require-jsdoc": "off", - "jsdoc/require-returns": "off", - "jsdoc/require-param-description": "off", - "jsdoc/require-param-type": "off", - "jsdoc/require-property-description": "off", - "jsdoc/require-returns-description": "off", - }, + extends: [configs["universal-recommended"]], }, ]); diff --git a/examples/on-listening/README.md b/examples/on-listening/README.md index c991b752b9..4bb0db9e77 100644 --- a/examples/on-listening/README.md +++ b/examples/on-listening/README.md @@ -9,7 +9,7 @@ module.exports = { // ... devServer: { onListening: (devServer) => { - const {port} = devServer.server.address(); + const { port } = devServer.server.address(); console.log("Listening on port:", port); }, }, diff --git a/lib/Server.js b/lib/Server.js index bd4348a667..314c26e389 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -2331,9 +2331,9 @@ class Server { if (newProxyConfig !== proxyConfig) { proxyConfig = newProxyConfig; - const socket = req.socket !== null ? req.socket : req.connection; + const socket = req.socket || req.connection; // @ts-expect-error - const server = socket !== null ? socket.server : null; + const server = socket ? socket.server : null; if (server) { server.removeAllListeners("close"); diff --git a/package-lock.json b/package-lock.json index df22096ede..bbfc523b5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -68,7 +68,7 @@ "css-loader": "^7.1.1", "eslint": "^9.30.1", "eslint-config-prettier": "^10.1.5", - "eslint-config-webpack": "^4.3.3", + "eslint-config-webpack": "^4.4.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jest": "^29.0.1", "eslint-plugin-jsdoc": "^51.3.4", @@ -8753,9 +8753,9 @@ } }, "node_modules/eslint-config-webpack": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/eslint-config-webpack/-/eslint-config-webpack-4.3.3.tgz", - "integrity": "sha512-5MB3a1zXhcHNafPw/Pyi2YkpSSkzWau6QuiwUglC1W9hkkFNbUFNll5XLpVen7UYz3gBQrHMH1yEGTMvh5k1WA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/eslint-config-webpack/-/eslint-config-webpack-4.4.0.tgz", + "integrity": "sha512-W0hMYVayDR4Sk+owcKtJDNEoiFDTHNzQJk/wnIBOxh6xjgOVj9MnHPtIP6AB3Ru2Suc+T8juIjfxyn3vuM0ptg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 84dfe33dc4..d0caa68b89 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "css-loader": "^7.1.1", "eslint": "^9.30.1", "eslint-config-prettier": "^10.1.5", - "eslint-config-webpack": "^4.3.3", + "eslint-config-webpack": "^4.4.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jest": "^29.0.1", "eslint-plugin-jsdoc": "^51.3.4", diff --git a/test/cli/basic.test.js b/test/cli/basic.test.js index 0aec509162..8de3726249 100644 --- a/test/cli/basic.test.js +++ b/test/cli/basic.test.js @@ -352,7 +352,7 @@ describe("basic", () => { /Project is running at http:\/\/localhost:(\d*)\//.exec(bits); if (portMatch) { - runtime.cp.port = portMatch[1]; + [, runtime.cp.port] = portMatch; } if (/Compiled successfully/.test(bits)) { @@ -367,7 +367,7 @@ describe("basic", () => { /Project is running at http:\/\/localhost:(\d*)\//.exec(bits); if (portMatch) { - runtime.cp2.port = portMatch[1]; + [, runtime.cp2.port] = portMatch; } if (/Compiled successfully/.test(bits)) { diff --git a/test/client/index.test.js b/test/client/index.test.js index 9f305318ac..aaa1c9f0f5 100644 --- a/test/client/index.test.js +++ b/test/client/index.test.js @@ -61,7 +61,7 @@ describe("index", () => { globalThis.location = { ...locationValue, reload: jest.fn() }; require("../../client-src"); - onSocketMessage = socket.mock.calls[0][1]; + [[, onSocketMessage]] = socket.mock.calls; }); afterEach(() => { @@ -182,7 +182,7 @@ describe("index", () => { overlay.send.mockReset(); socket.mockReset(); require("../../client-src"); - onSocketMessage = socket.mock.calls[0][1]; + [[, onSocketMessage]] = socket.mock.calls; onSocketMessage.warnings(["warn1"]); expect(overlay.send).not.toHaveBeenCalled(); @@ -204,7 +204,7 @@ describe("index", () => { overlay.send.mockReset(); socket.mockReset(); require("../../client-src"); - onSocketMessage = socket.mock.calls[0][1]; + [[, onSocketMessage]] = socket.mock.calls; onSocketMessage.errors(["error1"]); expect(overlay.send).not.toHaveBeenCalled(); @@ -224,7 +224,7 @@ describe("index", () => { socket.mockReset(); overlay.send.mockReset(); require("../../client-src"); - onSocketMessage = socket.mock.calls[0][1]; + [[, onSocketMessage]] = socket.mock.calls; onSocketMessage.warnings(["warn2"]); expect(overlay.send).toHaveBeenCalledTimes(1); diff --git a/test/client/socket-helper.test.js b/test/client/socket-helper.test.js index 504fbfb613..2ebcf25c98 100644 --- a/test/client/socket-helper.test.js +++ b/test/client/socket-helper.test.js @@ -23,7 +23,7 @@ describe("socket", () => { example: mockHandler, }); - const mockClientInstance = WebsocketClient.mock.instances[0]; + const [mockClientInstance] = WebsocketClient.mock.instances; // this simulates receiving a message from the server and passing it // along to the callback of onMessage @@ -56,8 +56,8 @@ describe("socket", () => { example: mockHandler, }); - const mockClientInstance = - globalThis.__webpack_dev_server_client__.mock.instances[0]; + const [mockClientInstance] = + globalThis.__webpack_dev_server_client__.mock.instances; // this simulates receiving a message from the server and passing it // along to the callback of onMessage diff --git a/test/e2e/ipc.test.js b/test/e2e/ipc.test.js index b96a0bcfb6..735b0e652f 100644 --- a/test/e2e/ipc.test.js +++ b/test/e2e/ipc.test.js @@ -98,7 +98,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://${devServerHost}:${proxyPort}/ws`, @@ -200,7 +200,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://${devServerHost}:${proxyPort}/ws`, @@ -320,7 +320,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://${devServerHost}:${proxyPort}/ws`, diff --git a/test/e2e/web-socket-server-url.test.js b/test/e2e/web-socket-server-url.test.js index 0f33a7a001..24147d0ba2 100644 --- a/test/e2e/web-socket-server-url.test.js +++ b/test/e2e/web-socket-server-url.test.js @@ -2195,7 +2195,7 @@ describe("web socket server URL", () => { waitUntil: "networkidle0", }); - const webSocketRequest = webSocketRequests[0]; + const [webSocketRequest] = webSocketRequests; expect(webSocketRequest.url).toContain( `${websocketURLProtocol}://${hostname}:${port1}/ws`, diff --git a/test/helpers/conditional-test.js b/test/helpers/conditional-test.js index 0dbc6af2fb..9a05682c72 100644 --- a/test/helpers/conditional-test.js +++ b/test/helpers/conditional-test.js @@ -4,6 +4,10 @@ const isWindows = process.platform === "win32"; +/** + * @param {string} reason reason + * @returns {boolean} true when it is windows, otherwise false + */ function skipTestOnWindows(reason) { if (isWindows) { test.skip(reason, () => {}); diff --git a/test/helpers/normalize-options.js b/test/helpers/normalize-options.js index 750497322f..923b8146e1 100644 --- a/test/helpers/normalize-options.js +++ b/test/helpers/normalize-options.js @@ -1,7 +1,8 @@ "use strict"; /** - * @param options + * @param {import("https").ServerOptions} options server options + * @returns {Record} normalized server options */ function normalizeOptions(options) { const normalizedOptions = {}; diff --git a/test/helpers/run-browser.js b/test/helpers/run-browser.js index b0fd6f86a0..e4d00b9ba9 100644 --- a/test/helpers/run-browser.js +++ b/test/helpers/run-browser.js @@ -64,7 +64,7 @@ function runPage(browser, device) { /** * @param {Device} device device - * @returns {Promise} + * @returns {Promise} browser result */ function runBrowser(device) { return new Promise((resolve, reject) => { diff --git a/test/helpers/test-server.js b/test/helpers/test-server.js index 7e9468f333..92af3ad815 100644 --- a/test/helpers/test-server.js +++ b/test/helpers/test-server.js @@ -3,23 +3,34 @@ const webpack = require("webpack"); const Server = require("../../lib/Server"); +/** @typedef {import("webpack").Configuration} Configuration */ +/** @typedef {import("../../lib/Server").Configuration} DevServerConfiguration */ +/** @typedef {import("webpack").Compiler} Compiler */ +/** @typedef {import("webpack").MultiCompiler} MultiCompiler */ + let server; // start server, returning the full setup of the server // (both the server and the compiler) -function startFullSetup(config, options, done) { +/** + * @param {Configuration} config configuration + * @param {DevServerConfiguration} devServerConfig dev server configuration + * @param {(err?: Error) => void=} done done callback + * @returns {{ server: Server, compiler: Compiler | MultiCompiler }} server and compiler + */ +function startFullSetup(config, devServerConfig, done) { // disable watching by default for tests - if (typeof options.static === "undefined") { - options.static = false; - } else if (options.static === null) { + if (typeof devServerConfig.static === "undefined") { + devServerConfig.static = false; + } else if (devServerConfig.static === null) { // this provides a way of using the default static value - delete options.static; + delete devServerConfig.static; } const compiler = webpack(config); - server = new Server(options, compiler); + server = new Server(devServerConfig, compiler); server.startCallback((error) => { if (error && done) { @@ -38,11 +49,12 @@ function startFullSetup(config, options, done) { } /** - * @param config - * @param options - * @param done + * @param {Configuration} config configuration + * @param {DevServerConfiguration} devServerConfig dev server configuration + * @param {(err?: Error) => void=} done done callback + * @returns {{ server: Server, compiler: Compiler | MultiCompiler }} server and compiler */ -function startAwaitingCompilationFullSetup(config, options, done) { +function start(config, devServerConfig, done) { let readyCount = 0; const ready = (error) => { @@ -59,7 +71,7 @@ function startAwaitingCompilationFullSetup(config, options, done) { } }; - const fullSetup = startFullSetup(config, options, ready); + const fullSetup = startFullSetup(config, devServerConfig, ready); // wait for compilation, since dev server can start before this // https://github.com/webpack/webpack-dev-server/issues/847 @@ -71,31 +83,7 @@ function startAwaitingCompilationFullSetup(config, options, done) { } /** - * @param config - * @param options - * @param done - */ -function startAwaitingCompilation(config, options, done) { - return startAwaitingCompilationFullSetup(config, options, done).server; -} - -/** - * @param config - * @param options - * @param done - */ -function start(config, options, done) { - // I suspect that almost all tests need to wait for compilation to - // finish, because not doing so leaves open handles for jest, - // in the case where a compilation didn't finish before destroying - // the server and moving on. Thus, the default "start" should wait - // for compilation, and only special cases where you don't expect - // a compilation happen should use startBeforeCompilation - return startAwaitingCompilation(config, options, done); -} - -/** - * @param done + * @param {() => void} done done callback */ function close(done) { if (server) { diff --git a/test/server/proxy-option.test.js b/test/server/proxy-option.test.js index 71ad20254f..4f445435fe 100644 --- a/test/server/proxy-option.test.js +++ b/test/server/proxy-option.test.js @@ -79,9 +79,9 @@ let maxServerListeners = 0; const proxyOptionOfArray = [ { context: "/proxy1", target: `http://localhost:${port1}` }, function proxy(req, res, next) { - if (req !== null) { - const socket = req.socket !== null ? req.socket : req.connection; - const server = socket !== null ? socket.server : null; + if (req) { + const socket = req.socket || req.connection; + const server = socket ? socket.server : null; if (server) { maxServerListeners = Math.max( maxServerListeners, From 877b527730d4e552c40cd800fb70f361480682a7 Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Tue, 15 Jul 2025 16:18:43 +0300 Subject: [PATCH 6/8] test: update --- .../server.test.js.snap.webpack5 | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/test/e2e/__snapshots__/server.test.js.snap.webpack5 b/test/e2e/__snapshots__/server.test.js.snap.webpack5 index 0f8208d2b1..7cd7e263a0 100644 --- a/test/e2e/__snapshots__/server.test.js.snap.webpack5 +++ b/test/e2e/__snapshots__/server.test.js.snap.webpack5 @@ -191,8 +191,6 @@ exports[`server option as object ca, pfx, key and cert are array of strings shou exports[`server option as object ca, pfx, key and cert are buffer should handle GET request to index route (/): console messages 1`] = `[]`; -exports[`server option as object ca, pfx, key and cert are buffer should handle GET request to index route (/): console messages 2`] = `[]`; - exports[`server option as object ca, pfx, key and cert are buffer should handle GET request to index route (/): https options 1`] = ` { "ca": "", @@ -204,35 +202,15 @@ exports[`server option as object ca, pfx, key and cert are buffer should handle } `; -exports[`server option as object ca, pfx, key and cert are buffer should handle GET request to index route (/): https options 2`] = ` -{ - "ca": "", - "cert": "", - "key": "", - "passphrase": "webpack-dev-server", - "pfx": "", - "requestCert": false, -} -`; - exports[`server option as object ca, pfx, key and cert are buffer should handle GET request to index route (/): page errors 1`] = `[]`; -exports[`server option as object ca, pfx, key and cert are buffer should handle GET request to index route (/): page errors 2`] = `[]`; - exports[`server option as object ca, pfx, key and cert are buffer should handle GET request to index route (/): response status 1`] = `200`; -exports[`server option as object ca, pfx, key and cert are buffer should handle GET request to index route (/): response status 2`] = `200`; - exports[`server option as object ca, pfx, key and cert are buffer should handle GET request to index route (/): response text 1`] = ` "Heyo. " `; -exports[`server option as object ca, pfx, key and cert are buffer should handle GET request to index route (/): response text 2`] = ` -"Heyo. -" -`; - exports[`server option as object ca, pfx, key and cert are buffer, key and pfx are objects should handle GET request to index route (/): console messages 1`] = `[]`; exports[`server option as object ca, pfx, key and cert are buffer, key and pfx are objects should handle GET request to index route (/): https options 1`] = ` From 4dd3d8aeda75fc17561a64069d8aedffc3657ce9 Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Tue, 15 Jul 2025 16:25:09 +0300 Subject: [PATCH 7/8] test: update --- .../cli/__snapshots__/server-option.test.js.snap.webpack5 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/cli/__snapshots__/server-option.test.js.snap.webpack5 b/test/cli/__snapshots__/server-option.test.js.snap.webpack5 index f3efb017ab..63c1199301 100644 --- a/test/cli/__snapshots__/server-option.test.js.snap.webpack5 +++ b/test/cli/__snapshots__/server-option.test.js.snap.webpack5 @@ -26,14 +26,6 @@ exports[`"server" CLI options should work using "--server-options-key --s [webpack-dev-server] Content not from webpack is served from '/public' directory" `; -exports[`"server" CLI options should work using "--server-options-key --server-options-pfx --server-options-passphrase webpack-dev-server --server-options-cert " 2`] = ` -" [webpack-dev-server] Project is running at: - Loopback: https://localhost:/, https://:/, https://[]:/ - [webpack-dev-server] On Your Network (IPv4): https://:/ - [webpack-dev-server] On Your Network (IPv6): https://[]:/ - [webpack-dev-server] Content not from webpack is served from '/public' directory" -`; - exports[`"server" CLI options should work using "--server-options-key-reset --server-options-key --server-options-pfx-reset --server-options-pfx --server-options-passphrase webpack-dev-server --server-options-cert-reset --server-options-cert --server-options-ca-reset --server-options-ca " 1`] = ` " [webpack-dev-server] Project is running at: Loopback: https://localhost:/, https://:/, https://[]:/ From ffd10fa0fe354746bc64f638ce928249fad108a7 Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Tue, 15 Jul 2025 16:48:32 +0300 Subject: [PATCH 8/8] test: update --- test/helpers/test-server.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/helpers/test-server.js b/test/helpers/test-server.js index 92af3ad815..9333c64601 100644 --- a/test/helpers/test-server.js +++ b/test/helpers/test-server.js @@ -52,7 +52,7 @@ function startFullSetup(config, devServerConfig, done) { * @param {Configuration} config configuration * @param {DevServerConfiguration} devServerConfig dev server configuration * @param {(err?: Error) => void=} done done callback - * @returns {{ server: Server, compiler: Compiler | MultiCompiler }} server and compiler + * @returns {Server} server */ function start(config, devServerConfig, done) { let readyCount = 0; @@ -71,15 +71,15 @@ function start(config, devServerConfig, done) { } }; - const fullSetup = startFullSetup(config, devServerConfig, ready); + const result = startFullSetup(config, devServerConfig, ready); // wait for compilation, since dev server can start before this // https://github.com/webpack/webpack-dev-server/issues/847 - fullSetup.compiler.hooks.done.tap("done", () => { + result.compiler.hooks.done.tap("done", () => { ready(); }); - return fullSetup; + return result.server; } /**