diff --git a/.changeset/finish-dev-server-migration.md b/.changeset/finish-dev-server-migration.md index a107d00a7..33056b140 100644 --- a/.changeset/finish-dev-server-migration.md +++ b/.changeset/finish-dev-server-migration.md @@ -2,4 +2,4 @@ "webpack-dev-middleware": minor --- -`hot.client: false` adds no runtime to the page while still applying `HotModuleReplacementPlugin`, which now goes to every compilation the middleware serves, including server bundles that hot-reload through `webpack/hot/poll`. `hot.client.transport` also accepts a module exporting a client class of your own, and the new `hot.ws` option is passed to the `ws` server (compression, `verifyClient`, or a `port` or `server` of its own), with `hot.cors` and `hot.token` still checked. The connection the runtime holds is exported as `webpack-dev-middleware/client/socket` for tooling that listens alongside it. +`HotModuleReplacementPlugin` now goes to every compilation the middleware serves, including server bundles that hot-reload through `webpack/hot/poll`. `hot.client.transport` also accepts a module exporting a client class of your own, and the new `hot.ws` option is passed to the `ws` server (compression, `verifyClient`, or a `port` or `server` of its own), with `hot.cors` and `hot.token` still checked. The connection the runtime holds is exported as `webpack-dev-middleware/client/socket` for tooling that listens alongside it. diff --git a/.changeset/hot-inject.md b/.changeset/hot-inject.md index 360605d49..d588bc34d 100644 --- a/.changeset/hot-inject.md +++ b/.changeset/hot-inject.md @@ -4,4 +4,4 @@ pr: #2430 -`hot` now adds the client and `HotModuleReplacementPlugin` to the compilation itself, so enabling it is all a webpack configuration needs; `hot.inject: false` turns this off for anyone wiring it by hand. Web workers get a client too, nothing is injected into a non-browser target, and the HMR plugin is left out when `hot.client.apply` is `reload` or `nothing`. +`hot` now adds the client and `HotModuleReplacementPlugin` to the compilation itself, so enabling it is all a webpack configuration needs. `hot.inject` says what is added: `"all"` (the default), `"plugin"` for a page with a client of its own, `"client"` for a configuration that applies the plugin itself, or `"none"`. Web workers get a client too, nothing is injected into a non-browser target, and the HMR plugin is left out when `hot.client.apply` is `reload` or `nothing`. diff --git a/README.md b/README.md index e784c949d..2e0583fa9 100644 --- a/README.md +++ b/README.md @@ -361,16 +361,16 @@ See [Hot Module Replacement client](#hot-module-replacement-client) for which co The object form accepts these options: -| Name | Type | Default | Description | -| :------------------------------------: | :-------------------------------------------------------------: | :----------------: | :-------------------------------------------------------------------------------------- | -| **[`transport`](#hottransport)** | `string \| function` | `'sse'` | How events reach the clients. | -| **[`path`](#hotpath)** | `string` | `'/__webpack_hmr'` | Path the endpoint is served at. | -| **[`heartbeat`](#hotheartbeat)** | `number` | `10000` | Interval (in milliseconds) between keep-alive frames. | -| **[`progress`](#hotprogress)** | `boolean` | `false` | Publish compilation progress events to the clients. | -| **[`cors`](#hotcors)** | `boolean \| string \| string[] \| RegExp \| function \| object` | see below | Which origins may reach the endpoint from a page on another one, over either transport. | -| **[`token`](#hottoken)** | `boolean \| string` | see below | A secret the injected client carries and the endpoint requires, over either transport. | -| **[`inject`](#hotinject)** | `boolean` | `true` | Add the client entry and `HotModuleReplacementPlugin`. | -| **[`statsOptions`](#hotstatsoptions)** | `object` | `undefined` | Deprecated — do not use; see [`stats`](#stats). | +| Name | Type | Default | Description | +| :------------------------------------: | :-------------------------------------------------------------: | :----------------: | :-------------------------------------------------------------------------------------------- | +| **[`transport`](#hottransport)** | `string \| function` | `'sse'` | How events reach the clients. | +| **[`path`](#hotpath)** | `string` | `'/__webpack_hmr'` | Path the endpoint is served at. | +| **[`heartbeat`](#hotheartbeat)** | `number` | `10000` | Interval (in milliseconds) between keep-alive frames. | +| **[`progress`](#hotprogress)** | `boolean` | `false` | Publish compilation progress events to the clients. | +| **[`cors`](#hotcors)** | `boolean \| string \| string[] \| RegExp \| function \| object` | see below | Which origins may reach the endpoint from a page on another one, over either transport. | +| **[`token`](#hottoken)** | `boolean \| string` | see below | A secret the injected client carries and the endpoint requires, over either transport. | +| **[`inject`](#hotinject)** | `"all" \| "plugin" \| "client" \| "none"` | `"all"` | What is added to the compilation: the runtime, `HotModuleReplacementPlugin`, both or neither. | +| **[`statsOptions`](#hotstatsoptions)** | `object` | `undefined` | Deprecated — do not use; see [`stats`](#stats). | #### `hot.transport` @@ -615,7 +615,7 @@ client entry was added to hand one over, so every client will be refused. > > **What a token does not protect.** The client reads it from its entry query, so it is a string in the bundle. Anything that can already read your bundle cross-origin can read the token out of it — and over plain `http` to a non-`localhost` address, nothing stops that unless your server sends `Cross-Origin-Resource-Policy`. The token hardens every case where the bundle is not readable; where it is, your source has already gone and the stream is the smaller loss. Closing that needs the response header and a `Host` allowlist, which are [your server's](#security) to set. -**Wiring the client yourself.** The token travels in the entry this middleware adds, so `hot.inject: false` turns the requirement off — there would be no way to hand one over, and requiring it would refuse a client you wired correctly. +**Wiring the client yourself.** The token travels in the entry this middleware adds, so `hot.inject: "plugin"` or `"none"` turns off the default requirement — there would be no way to hand one over, and requiring it would refuse a client you wired correctly. A `hot.token` you set to `true` or a string is still required: hand it to your client yourself, as below, or set `hot.token: false`. A configuration that already lists the client as an entry is the other half of that: it is built before the middleware exists, so it cannot carry a token minted per run. Give it one of your own instead, which both sides can know in advance: @@ -645,12 +645,17 @@ app.get("/my-client-config.json", (_req, res) => { #### `hot.inject` -Type: `Boolean` -Default: `true` +Type: `"all" | "plugin" | "client" | "none"` +Default: `"all"` -Add the client entry and `HotModuleReplacementPlugin` to the compilation. Set it to `false` to wire both yourself — see [Hot Module Replacement client](#hot-module-replacement-client). To keep the plugin and wire only the client yourself, set [`hot.client`](#client-options) to `false` instead. +What the middleware adds to the compilation. There are two pieces: the runtime in the page — this package's client, with its overlay and building indicator — and `HotModuleReplacementPlugin`, which is webpack's own hot logic. -Turn it off when you have a client of your own that the middleware will not recognize as one (anything other than `webpack-dev-middleware/client`), or when you do not want the hot runtime in your bundle at all and are using the endpoint through [`subscribe`](#custom-events) instead. +| Value | Runtime | Plugin | For | +| :--------- | :-----: | :----: | :--------------------------------------------------------------------------------------------------------------- | +| `"all"` | ✓ | ✓ | the default: nothing to add to the webpack configuration | +| `"plugin"` | | ✓ | a page that wires a client of its own — one the middleware does not recognize as its own | +| `"client"` | ✓ | | a configuration that applies `HotModuleReplacementPlugin` itself, or wants the page reloaded without the runtime | +| `"none"` | | | wiring both yourself, or using the endpoint only through [`subscribe`](#custom-events) | #### `hot.statsOptions` @@ -682,7 +687,7 @@ app.use(middleware(compiler, { hot: true })); The runtime is told the endpoint and the transport the middleware resolved, so the two agree without the same value being written in two places. -Set `hot.inject` to `false` to wire it yourself instead — the runtime is published under the `./client` subpath: +Set `hot.inject` to `"plugin"` to wire it yourself instead (or `"none"` to apply the plugin yourself as well) — the runtime is published under the `./client` subpath: ```js const webpack = require("webpack"); @@ -693,9 +698,9 @@ module.exports = { }; ``` -An entry point that already has the client is left alone, so this keeps working without `hot.inject: false`. It is decided per entry point rather than per compilation: in a build with `landing` and `dashboard` where only `landing` has the client, `dashboard` still gets one, because they are separate pages and it would otherwise connect to nothing. +An entry point that already has the client is left alone, so this keeps working with the default `hot.inject`. It is decided per entry point rather than per compilation: in a build with `landing` and `dashboard` where only `landing` has the client, `dashboard` still gets one, because they are separate pages and it would otherwise connect to nothing. -The client is recognized as `webpack-dev-middleware/client` (with or without a query) or as the path that resolves to, so your own `./src/client/index.js` is your own file. It is a best effort over the `entry` shapes it can read: a function is computed per build and cannot be read, and a request can reach the client through an alias or a loader. Missing one costs a duplicate entry, not a broken build, and `hot.inject: false` is the way out. +The client is recognized as `webpack-dev-middleware/client` (with or without a query) or as the path that resolves to, so your own `./src/client/index.js` is your own file. It is a best effort over the `entry` shapes it can read: a function is computed per build and cannot be read, and a request can reach the client through an alias or a loader. Missing one costs a duplicate entry, not a broken build, and `hot.inject: "plugin"` is the way out. #### Which compilations get the runtime @@ -728,10 +733,10 @@ Nothing has to change, and both pieces are recognized rather than duplicated: - An entry that is already `webpack-dev-middleware/client` (with or without a query) is left as it is. - `HotModuleReplacementPlugin` already in `plugins` is not applied twice. It is now redundant, and the middleware says so once per build so you can drop it. -Two things do change, and `hot.inject: false` turns both off: +Two things do change: -- **A client the middleware does not recognize** — anything other than `webpack-dev-middleware/client`, such as another package's hot client — is not detected, so a second client is added and both connect. -- **A project with no `HotModuleReplacementPlugin` on purpose** now gets one, which puts the HMR runtime in the bundle and changes its output. If you only wanted the endpoint to listen to through [`subscribe`](#custom-events), set `hot.inject: false`. A project that sets [`hot.client.apply`](#client-options) to `reload` or `nothing` does not: those modes never use the HMR runtime, so it is left out, and a plugin you wrote into the configuration yourself stays. A page whose url asks for `hmr` or `hmr-only` against such a bundle has no runtime to apply an update with, so `hmr` loads the page instead, and `hmr-only` says so and stops. (A runtime that is missing from a project whose own mode wanted it is a mistake, and is reported once instead of reloading.) +- **A client the middleware does not recognize** — anything other than `webpack-dev-middleware/client`, such as another package's hot client — is not detected, so a second client is added and both connect. `hot.inject: "plugin"` turns that off. +- **A project with no `HotModuleReplacementPlugin` on purpose** now gets one, which puts the HMR runtime in the bundle and changes its output. `hot.inject: "client"` turns that off; if you only wanted the endpoint to listen to through [`subscribe`](#custom-events), set `hot.inject: "none"`. A project that sets [`hot.client.apply`](#client-options) to `reload` or `nothing` does not: those modes never use the HMR runtime, so it is left out, and a plugin you wrote into the configuration yourself stays. A page whose url asks for `hmr` or `hmr-only` against such a bundle has no runtime to apply an update with, so `hmr` loads the page instead, and `hmr-only` says so and stops. (A runtime that is missing from a project whose own mode wanted it is a mistake, and is reported once instead of reloading.) A package of your own can stand in for the client by re-exporting it. A query written on that module belongs to it rather than to the client, so leave it where the client looks, before requiring the client: @@ -744,7 +749,7 @@ module.exports = require("webpack-dev-middleware/client"); One caveat: if the compiler was already watching before the middleware was created, the runtime appears from the next build onwards rather than the first one. Create the middleware before starting the watch to avoid it. -No client is added when [`hot.transport`](#hottransport) is a function either — the built-in one speaks Server-Sent Events and WebSocket, and a transport of your own carries whatever protocol you wrote it to carry, so the client that speaks it is yours to add unless [`hot.client.transport`](#client-options) says which of the two yours speaks. `HotModuleReplacementPlugin` is still applied for you. `hot.inject: false` silences the reminder, and turns that off as well — apply the plugin yourself if you use it. +No client is added when [`hot.transport`](#hottransport) is a function either — the built-in one speaks Server-Sent Events and WebSocket, and a transport of your own carries whatever protocol you wrote it to carry, so the client that speaks it is yours to add unless [`hot.client.transport`](#client-options) says which of the two yours speaks. `HotModuleReplacementPlugin` is still applied for you. `hot.inject: "plugin"` silences the reminder. The [client options](#client-options) below are set on the middleware, next to the rest of the hot configuration, and the injected entry carries them to the @@ -808,12 +813,8 @@ app.use( ); ``` -`hot.client: false` adds no runtime to the page and still applies -`HotModuleReplacementPlugin`, for a page that wires a client of its own and -still wants its updates applied. - -`hot.client` is read only when the client is injected. With `hot.inject: false`, -or for a client the configuration already has as an entry, the query string on +`hot.client` is read only when the client is injected. With +[`hot.inject`](#hotinject) set to `"plugin"` or `"none"`, or for a client the configuration already has as an entry, the query string on the entry path is the only source — and it works either way: ```js diff --git a/src/hot.js b/src/hot.js index 3fbaa9d20..7c0574b40 100644 --- a/src/hot.js +++ b/src/hot.js @@ -62,8 +62,8 @@ * @property {boolean=} progress publish compilation progress events to the clients * @property {CorsOption=} cors which origins may reach the endpoint from a page on another one; the local ones by default * @property {(boolean | string)=} token a secret the injected client carries and the endpoint requires; `true` mints one per run, a string uses that one, `false` requires none. Defaults to `false` on both transports; `true` in the next major release - * @property {boolean=} inject add the hot client entry and `HotModuleReplacementPlugin` to the compilation (default `true`); turn it off to wire them yourself - * @property {(HotClientOptions | false)=} client options handed to the browser runtime through its entry query; `false` adds no runtime to the page and still applies `HotModuleReplacementPlugin` + * @property {("all" | "plugin" | "client" | "none")=} inject what is added to the compilation: the runtime and `HotModuleReplacementPlugin` (`"all"`, the default), the plugin alone for a page that wires a client of its own, the runtime alone for a configuration that applies the plugin itself, or nothing + * @property {HotClientOptions=} client options handed to the browser runtime through its entry query */ /** @@ -489,12 +489,14 @@ function createHot(compiler, userOptions, statsOption) { const transport = options.transport || HOT_DEFAULT_TRANSPORT; const { cors } = options; const { statsOptions } = options; - // `inject: false` turns it off: the token reaches the browser through the - // entry this middleware adds, so with nothing injected there is no way to - // hand one over, and requiring it would refuse a client the developer wired + // Off when no client is injected: the token reaches the browser through the + // entry this middleware adds, so with none added there is no way to hand one + // over, and requiring it would refuse a client the developer wired // correctly. Off by default either way — see `HOT_DEFAULT_TOKEN`. + const injectsClient = + !options.inject || options.inject === "all" || options.inject === "client"; const token = resolveToken( - options.inject === false ? (options.token ?? false) : options.token, + injectsClient ? options.token : (options.token ?? false), ); const logger = compiler.getInfrastructureLogger("webpack-dev-middleware"); diff --git a/src/options.check.js b/src/options.check.js index 474c7f9d3..cfbae472b 100644 --- a/src/options.check.js +++ b/src/options.check.js @@ -2,4 +2,4 @@ // DO NOT MODIFY BY HAND. Run `npm run fix:schema-check` to update. /* eslint-disable */ // @ts-nocheck -"use strict";module.exports = validate10;module.exports.default = validate10;const schema11 = {"definitions":{"HotClient":{"description":"Options handed to the browser runtime through its entry query.","type":"object","additionalProperties":false,"properties":{"transport":{"description":"Which transport the runtime speaks: `sse` or `ws`, or a module that exports a client class of your own, which is used in place of the built-in one. Defaults to the resolved `hot.transport`.","anyOf":[{"enum":["sse","ws"]},{"type":"string","minLength":1}]},"url":{"description":"Where the runtime connects: a path, an absolute url for an endpoint reached on another origin or through a proxy, or the parts of one that differ, with the rest resolved in the page, which is the only place the rest is known. Defaults to the resolved `hot.path`.","anyOf":[{"type":"string","minLength":1},{"type":"object","additionalProperties":false,"properties":{"protocol":{"description":"The scheme the runtime connects over. Unset, or `auto`, follows the page — and a page served over TLS then gets a secure connection, because a browser refuses a plaintext one from it. Set explicitly, it is honoured as given; the one exception is a `hostname` naming every interface, which is resolved to the page's host and takes the page's scheme with it. Only whether the scheme is the secure one carries over, since the two transports do not share one.","anyOf":[{"enum":["auto"]},{"type":"string","minLength":1}]},"hostname":{"description":"The host the runtime connects to. An address a server listens on to mean every interface (`0.0.0.0`, `::`) is not somewhere a page can connect, so it resolves to the page's own host.","type":"string","minLength":1},"port":{"description":"The port the runtime connects to. `0` means a port the server picked, which resolves to the page's own.","anyOf":[{"type":"number"},{"type":"string","minLength":1}]},"pathname":{"description":"The path the runtime connects to. Defaults to the resolved `hot.path`.","type":"string"},"username":{"description":"The username the runtime authenticates with.","type":"string"},"password":{"description":"The password the runtime authenticates with. Sent only alongside a username, since basic authentication has no empty one.","type":"string"}}}]},"name":{"description":"Limit the runtime to one compilation's builds. Defaults to the compilation's own name.","type":"string"},"overlay":{"description":"Show build problems and uncaught runtime errors in an overlay.","anyOf":[{"type":"boolean"},{"type":"object"}]},"progress":{"description":"Show an indicator while a rebuild is in progress.","anyOf":[{"type":"boolean"},{"enum":["circular","linear"]}]},"apply":{"description":"What a build does to the page: `hmr` applies the update and reloads if it cannot be applied, `hmr-only` applies it and stops with a message if it cannot, `reload` loads the page again on a build that changed something, and `nothing` leaves the page alone until you reload it.","enum":["hmr","hmr-only","reload","nothing"]},"connect":{"description":"Whether to connect when the entry runs, and how the connection is held open. `false` does not connect; an object sets `retries` and `timeout`.","anyOf":[{"type":"boolean"},{"type":"object","additionalProperties":false,"properties":{"retries":{"description":"How many times to reconnect before giving up. Server-Sent Events keep trying for as long as the page is open unless this is set, since a dev server is expected to come back.","type":"number","minimum":0},"timeout":{"description":"How long silence is tolerated before reconnecting, in milliseconds. Server-Sent Events only: their heartbeat arrives as data the client can see, whereas a WebSocket's is a protocol ping the browser answers without telling JavaScript.","type":"number","minimum":1}}}]},"pageParamPrefix":{"description":"Prefix of the page-url parameters that override `apply` for a single page, as in `?webpack-dev-middleware-hot=false`.","type":"string","minLength":1},"logging":{"description":"Logger level in the browser, or an object carrying the level and the name every message is labelled with in the console — a package embedding this runtime is the one a developer would report a problem to, so it can say its own name.","anyOf":[{"enum":["none","error","warn","info","log","verbose"]},{"type":"object","additionalProperties":false,"properties":{"level":{"enum":["none","error","warn","info","log","verbose"]},"name":{"description":"What every message is labelled with in the console. Defaults to this package's name.","type":"string","minLength":1}}}]},"dynamicPublicPath":{"description":"Prefix the endpoint path with the bundle's public path at runtime.","type":"boolean"}}},"CorsOrigin":{"description":"An origin, written as a browser sends it (scheme, host and port, no trailing slash), several of them, a pattern, or a function asked about each.","anyOf":[{"type":"string","minLength":1},{"instanceof":"RegExp"},{"type":"array","items":{"anyOf":[{"type":"string","minLength":1},{"instanceof":"RegExp"}]},"minItems":1},{"instanceof":"Function"}]}},"type":"object","properties":{"cache":{"description":"How responses are cached.","link":"https://github.com/webpack/webpack-dev-middleware#cache","type":"object","additionalProperties":false,"properties":{"etag":{"description":"Enable or disable etag generation.","enum":["weak","strong"]},"lastModified":{"description":"Enable or disable `Last-Modified` header. Uses the file system's last modified value.","type":"boolean"},"control":{"description":"Enable or disable setting `Cache-Control` response header.","anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string","minLength":1},{"type":"object","properties":{"maxAge":{"type":"number"},"immutable":{"type":"boolean"}},"additionalProperties":false}]},"immutable":{"description":"Enable or disable setting `Cache-Control: public, max-age=31536000, immutable` response header for immutable assets (i.e. asset with a hash in file name like `image.a4c12bde.jpg`).","type":"boolean"}}},"mime":{"description":"How a file's media type is decided.","link":"https://github.com/webpack/webpack-dev-middleware#mime","type":"object","additionalProperties":false,"properties":{"types":{"description":"Allows a user to register custom mime types or extension mappings.","type":"object"},"default":{"description":"Allows a user to register a default mime type when we can't determine the content type.","type":"string"}}},"mimeTypes":{"description":"Allows a user to register custom mime types or extension mappings.","link":"https://github.com/webpack/webpack-dev-middleware#mimetypes","type":"object"},"mimeTypeDefault":{"description":"Allows a user to register a default mime type when we can't determine the content type.","link":"https://github.com/webpack/webpack-dev-middleware#mimetypedefault","type":"string"},"writeToDisk":{"description":"Allows to write generated files on disk.","link":"https://github.com/webpack/webpack-dev-middleware#writetodisk","anyOf":[{"type":"boolean"},{"instanceof":"Function"}]},"methods":{"description":"Allows to pass the list of HTTP request methods accepted by the middleware.","link":"https://github.com/webpack/webpack-dev-middleware#methods","type":"array","items":{"type":"string","minLength":1}},"headers":{"anyOf":[{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"key":{"description":"key of header.","type":"string"},"value":{"description":"value of header.","type":"string"}}},"minItems":1},{"type":"object"},{"instanceof":"Function"}],"description":"Allows to pass custom HTTP headers on each request","link":"https://github.com/webpack/webpack-dev-middleware#headers"},"publicPath":{"description":"The `publicPath` specifies the public URL address of the output files when referenced in a browser.","link":"https://github.com/webpack/webpack-dev-middleware#publicpath","anyOf":[{"enum":["auto"]},{"type":"string"},{"instanceof":"Function"}]},"stats":{"description":"Stats options object or preset name.","link":"https://github.com/webpack/webpack-dev-middleware#stats","anyOf":[{"enum":["none","summary","errors-only","errors-warnings","minimal","normal","detailed","verbose"]},{"type":"boolean"},{"type":"object","additionalProperties":true}]},"serverSideRender":{"description":"Instructs the module to enable or disable the server-side rendering mode.","link":"https://github.com/webpack/webpack-dev-middleware#serversiderender","type":"boolean"},"outputFileSystem":{"description":"Set the default file system which will be used by webpack as primary destination of generated files.","link":"https://github.com/webpack/webpack-dev-middleware#outputfilesystem","type":"object"},"index":{"description":"Allows to serve an index of the directory.","link":"https://github.com/webpack/webpack-dev-middleware#index","anyOf":[{"type":"boolean"},{"type":"string","minLength":1}]},"modifyResponseData":{"description":"Allows to set up a callback to change the response data.","link":"https://github.com/webpack/webpack-dev-middleware#modifyresponsedata","instanceof":"Function"},"etag":{"description":"Enable or disable etag generation.","link":"https://github.com/webpack/webpack-dev-middleware#etag","enum":["weak","strong"]},"lastModified":{"description":"Enable or disable `Last-Modified` header. Uses the file system's last modified value.","link":"https://github.com/webpack/webpack-dev-middleware#lastmodified","type":"boolean"},"cacheControl":{"description":"Enable or disable setting `Cache-Control` response header.","link":"https://github.com/webpack/webpack-dev-middleware#cachecontrol","anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string","minLength":1},{"type":"object","properties":{"maxAge":{"type":"number"},"immutable":{"type":"boolean"}},"additionalProperties":false}]},"cacheImmutable":{"description":"Enable or disable setting `Cache-Control: public, max-age=31536000, immutable` response header for immutable assets (i.e. asset with a hash in file name like `image.a4c12bde.jpg`).","link":"https://github.com/webpack/webpack-dev-middleware#cacheimmutable","type":"boolean"},"forwardError":{"description":"Enable or disable forwarding errors to next middleware.","link":"https://github.com/webpack/webpack-dev-middleware#forwarderrors","type":"boolean"},"hot":{"description":"Enable hot module replacement over a Server-Sent Events or WebSocket endpoint.","link":"https://github.com/webpack/webpack-dev-middleware#hot","anyOf":[{"type":"boolean"},{"type":"object","additionalProperties":false,"properties":{"transport":{"description":"How events reach the clients: `sse`, `ws` (needs the optional `ws` dependency and the upgrades of an HTTP server: hand the server to the middleware's `attach(server)`, or pass each upgrade to `handleUpgrade(req, socket, head)`), or a function building a transport of your own.","anyOf":[{"enum":["sse","ws"]},{"instanceof":"Function"}]},"path":{"description":"The path the endpoint is served at. Must start with a slash and carry no query string or fragment.","type":"string","pattern":"^/[^?#]*$"},"heartbeat":{"description":"Heartbeat interval (in milliseconds) used to keep the connection alive.","type":"number","minimum":1},"ws":{"description":"Options for the `ws` server behind the `ws` transport: compression, payload limits, `verifyClient`, or a `port` or a `server` of its own to listen on instead of answering the upgrades it is handed. `path`, `noServer` and `clientTracking` are the middleware's and are ignored here.","link":"https://github.com/webpack/webpack-dev-middleware#hot","type":"object","additionalProperties":true},"progress":{"description":"Publish compilation progress events to the clients.","type":"boolean"},"token":{"description":"A secret the injected client carries and the endpoint requires, so reaching the stream takes something a page has to have been given rather than a header the browser may not send. `true` mints one per run, a string uses that one — for a client of your own that has to build the url itself — and `false` requires none. Defaults to `false`, because requiring one would refuse a client this middleware did not inject; `true` in the next major release.","link":"https://github.com/webpack/webpack-dev-middleware#hottoken","anyOf":[{"type":"boolean"},{"type":"string","minLength":1}]},"cors":{"description":"Which origins may read the Server-Sent Events endpoint from a page on another one. Local origins only by default. `true` grants every origin, which lets any site the developer has open read the build's errors, including the source frames webpack puts in them.","link":"https://github.com/webpack/webpack-dev-middleware#hotcors","anyOf":[{"type":"boolean"},{"$ref":"#/definitions/CorsOrigin"},{"type":"object","additionalProperties":false,"properties":{"origin":{"description":"Which origins may read it, as Vite and `expressjs/cors` are configured.","anyOf":[{"type":"boolean"},{"$ref":"#/definitions/CorsOrigin"}]}}}]},"statsOptions":{"description":"Deprecated, do not use, will be removed in the next major release. Use the `stats` option instead, which decides whether a payload carries errors and warnings.","type":"object","additionalProperties":true},"inject":{"description":"Add the hot client entry and HotModuleReplacementPlugin to the compilation. Turn it off to wire them yourself.","link":"https://github.com/webpack/webpack-dev-middleware#hot","type":"boolean"},"client":{"description":"Options handed to the browser runtime through its entry query. `false` adds no runtime to the page while still applying `HotModuleReplacementPlugin`, for a page that wires a client of its own.","link":"https://github.com/webpack/webpack-dev-middleware#hot","anyOf":[{"enum":[false]},{"$ref":"#/definitions/HotClient"}]}}}]}},"additionalProperties":false};const schema12 = {"description":"An origin, written as a browser sends it (scheme, host and port, no trailing slash), several of them, a pattern, or a function asked about each.","anyOf":[{"type":"string","minLength":1},{"instanceof":"RegExp"},{"type":"array","items":{"anyOf":[{"type":"string","minLength":1},{"instanceof":"RegExp"}]},"minItems":1},{"instanceof":"Function"}]};const schema14 = {"description":"Options handed to the browser runtime through its entry query.","type":"object","additionalProperties":false,"properties":{"transport":{"description":"Which transport the runtime speaks: `sse` or `ws`, or a module that exports a client class of your own, which is used in place of the built-in one. Defaults to the resolved `hot.transport`.","anyOf":[{"enum":["sse","ws"]},{"type":"string","minLength":1}]},"url":{"description":"Where the runtime connects: a path, an absolute url for an endpoint reached on another origin or through a proxy, or the parts of one that differ, with the rest resolved in the page, which is the only place the rest is known. Defaults to the resolved `hot.path`.","anyOf":[{"type":"string","minLength":1},{"type":"object","additionalProperties":false,"properties":{"protocol":{"description":"The scheme the runtime connects over. Unset, or `auto`, follows the page — and a page served over TLS then gets a secure connection, because a browser refuses a plaintext one from it. Set explicitly, it is honoured as given; the one exception is a `hostname` naming every interface, which is resolved to the page's host and takes the page's scheme with it. Only whether the scheme is the secure one carries over, since the two transports do not share one.","anyOf":[{"enum":["auto"]},{"type":"string","minLength":1}]},"hostname":{"description":"The host the runtime connects to. An address a server listens on to mean every interface (`0.0.0.0`, `::`) is not somewhere a page can connect, so it resolves to the page's own host.","type":"string","minLength":1},"port":{"description":"The port the runtime connects to. `0` means a port the server picked, which resolves to the page's own.","anyOf":[{"type":"number"},{"type":"string","minLength":1}]},"pathname":{"description":"The path the runtime connects to. Defaults to the resolved `hot.path`.","type":"string"},"username":{"description":"The username the runtime authenticates with.","type":"string"},"password":{"description":"The password the runtime authenticates with. Sent only alongside a username, since basic authentication has no empty one.","type":"string"}}}]},"name":{"description":"Limit the runtime to one compilation's builds. Defaults to the compilation's own name.","type":"string"},"overlay":{"description":"Show build problems and uncaught runtime errors in an overlay.","anyOf":[{"type":"boolean"},{"type":"object"}]},"progress":{"description":"Show an indicator while a rebuild is in progress.","anyOf":[{"type":"boolean"},{"enum":["circular","linear"]}]},"apply":{"description":"What a build does to the page: `hmr` applies the update and reloads if it cannot be applied, `hmr-only` applies it and stops with a message if it cannot, `reload` loads the page again on a build that changed something, and `nothing` leaves the page alone until you reload it.","enum":["hmr","hmr-only","reload","nothing"]},"connect":{"description":"Whether to connect when the entry runs, and how the connection is held open. `false` does not connect; an object sets `retries` and `timeout`.","anyOf":[{"type":"boolean"},{"type":"object","additionalProperties":false,"properties":{"retries":{"description":"How many times to reconnect before giving up. Server-Sent Events keep trying for as long as the page is open unless this is set, since a dev server is expected to come back.","type":"number","minimum":0},"timeout":{"description":"How long silence is tolerated before reconnecting, in milliseconds. Server-Sent Events only: their heartbeat arrives as data the client can see, whereas a WebSocket's is a protocol ping the browser answers without telling JavaScript.","type":"number","minimum":1}}}]},"pageParamPrefix":{"description":"Prefix of the page-url parameters that override `apply` for a single page, as in `?webpack-dev-middleware-hot=false`.","type":"string","minLength":1},"logging":{"description":"Logger level in the browser, or an object carrying the level and the name every message is labelled with in the console — a package embedding this runtime is the one a developer would report a problem to, so it can say its own name.","anyOf":[{"enum":["none","error","warn","info","log","verbose"]},{"type":"object","additionalProperties":false,"properties":{"level":{"enum":["none","error","warn","info","log","verbose"]},"name":{"description":"What every message is labelled with in the console. Defaults to this package's name.","type":"string","minLength":1}}}]},"dynamicPublicPath":{"description":"Prefix the endpoint path with the bundle's public path at runtime.","type":"boolean"}}};const func2 = Object.prototype.hasOwnProperty;const pattern0 = new RegExp("^/[^?#]*$", "u");function validate10(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){let vErrors = null;let errors = 0;if(errors === 0){if(data && typeof data == "object" && !Array.isArray(data)){const _errs1 = errors;for(const key0 in data){if(!(func2.call(schema11.properties, key0))){validate10.errors = [{instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}];return false;break;}}if(_errs1 === errors){if(data.cache !== undefined){let data0 = data.cache;const _errs2 = errors;if(errors === _errs2){if(data0 && typeof data0 == "object" && !Array.isArray(data0)){const _errs5 = errors;for(const key1 in data0){if(!((((key1 === "etag") || (key1 === "lastModified")) || (key1 === "control")) || (key1 === "immutable"))){validate10.errors = [{instancePath:instancePath+"/cache",schemaPath:"#/properties/cache/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}];return false;break;}}if(_errs5 === errors){if(data0.etag !== undefined){let data1 = data0.etag;const _errs6 = errors;if(!((data1 === "weak") || (data1 === "strong"))){validate10.errors = [{instancePath:instancePath+"/cache/etag",schemaPath:"#/properties/cache/properties/etag/enum",keyword:"enum",params:{allowedValues: schema11.properties.cache.properties.etag.enum},message:"must be equal to one of the allowed values"}];return false;}var valid1 = _errs6 === errors;}else {var valid1 = true;}if(valid1){if(data0.lastModified !== undefined){const _errs7 = errors;if(typeof data0.lastModified !== "boolean"){validate10.errors = [{instancePath:instancePath+"/cache/lastModified",schemaPath:"#/properties/cache/properties/lastModified/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}];return false;}var valid1 = _errs7 === errors;}else {var valid1 = true;}if(valid1){if(data0.control !== undefined){let data3 = data0.control;const _errs9 = errors;const _errs10 = errors;let valid2 = false;const _errs11 = errors;if(typeof data3 !== "boolean"){const err0 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/0/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}var _valid0 = _errs11 === errors;valid2 = valid2 || _valid0;if(!valid2){const _errs13 = errors;if(!(typeof data3 == "number")){const err1 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/1/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}var _valid0 = _errs13 === errors;valid2 = valid2 || _valid0;if(!valid2){const _errs15 = errors;if(errors === _errs15){if(typeof data3 === "string"){if(data3.length < 1){const err2 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/2/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}}else {const err3 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/2/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}}var _valid0 = _errs15 === errors;valid2 = valid2 || _valid0;if(!valid2){const _errs17 = errors;if(errors === _errs17){if(data3 && typeof data3 == "object" && !Array.isArray(data3)){const _errs19 = errors;for(const key2 in data3){if(!((key2 === "maxAge") || (key2 === "immutable"))){const err4 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/3/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;break;}}if(_errs19 === errors){if(data3.maxAge !== undefined){const _errs20 = errors;if(!(typeof data3.maxAge == "number")){const err5 = {instancePath:instancePath+"/cache/control/maxAge",schemaPath:"#/properties/cache/properties/control/anyOf/3/properties/maxAge/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}var valid3 = _errs20 === errors;}else {var valid3 = true;}if(valid3){if(data3.immutable !== undefined){const _errs22 = errors;if(typeof data3.immutable !== "boolean"){const err6 = {instancePath:instancePath+"/cache/control/immutable",schemaPath:"#/properties/cache/properties/control/anyOf/3/properties/immutable/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}var valid3 = _errs22 === errors;}else {var valid3 = true;}}}}else {const err7 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/3/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}}var _valid0 = _errs17 === errors;valid2 = valid2 || _valid0;}}}if(!valid2){const err8 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;validate10.errors = vErrors;return false;}else {errors = _errs10;if(vErrors !== null){if(_errs10){vErrors.length = _errs10;}else {vErrors = null;}}}var valid1 = _errs9 === errors;}else {var valid1 = true;}if(valid1){if(data0.immutable !== undefined){const _errs24 = errors;if(typeof data0.immutable !== "boolean"){validate10.errors = [{instancePath:instancePath+"/cache/immutable",schemaPath:"#/properties/cache/properties/immutable/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}];return false;}var valid1 = _errs24 === errors;}else {var valid1 = true;}}}}}}else {validate10.errors = [{instancePath:instancePath+"/cache",schemaPath:"#/properties/cache/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid0 = _errs2 === errors;}else {var valid0 = true;}if(valid0){if(data.mime !== undefined){let data7 = data.mime;const _errs26 = errors;if(errors === _errs26){if(data7 && typeof data7 == "object" && !Array.isArray(data7)){const _errs29 = errors;for(const key3 in data7){if(!((key3 === "types") || (key3 === "default"))){validate10.errors = [{instancePath:instancePath+"/mime",schemaPath:"#/properties/mime/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}];return false;break;}}if(_errs29 === errors){if(data7.types !== undefined){let data8 = data7.types;const _errs30 = errors;if(!(data8 && typeof data8 == "object" && !Array.isArray(data8))){validate10.errors = [{instancePath:instancePath+"/mime/types",schemaPath:"#/properties/mime/properties/types/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}var valid4 = _errs30 === errors;}else {var valid4 = true;}if(valid4){if(data7.default !== undefined){const _errs32 = errors;if(typeof data7.default !== "string"){validate10.errors = [{instancePath:instancePath+"/mime/default",schemaPath:"#/properties/mime/properties/default/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}var valid4 = _errs32 === errors;}else {var valid4 = true;}}}}else {validate10.errors = [{instancePath:instancePath+"/mime",schemaPath:"#/properties/mime/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid0 = _errs26 === errors;}else {var valid0 = true;}if(valid0){if(data.mimeTypes !== undefined){let data10 = data.mimeTypes;const _errs34 = errors;if(!(data10 && typeof data10 == "object" && !Array.isArray(data10))){validate10.errors = [{instancePath:instancePath+"/mimeTypes",schemaPath:"#/properties/mimeTypes/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}var valid0 = _errs34 === errors;}else {var valid0 = true;}if(valid0){if(data.mimeTypeDefault !== undefined){const _errs37 = errors;if(typeof data.mimeTypeDefault !== "string"){validate10.errors = [{instancePath:instancePath+"/mimeTypeDefault",schemaPath:"#/properties/mimeTypeDefault/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}var valid0 = _errs37 === errors;}else {var valid0 = true;}if(valid0){if(data.writeToDisk !== undefined){let data12 = data.writeToDisk;const _errs40 = errors;const _errs41 = errors;let valid5 = false;const _errs42 = errors;if(typeof data12 !== "boolean"){const err9 = {instancePath:instancePath+"/writeToDisk",schemaPath:"#/properties/writeToDisk/anyOf/0/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}var _valid1 = _errs42 === errors;valid5 = valid5 || _valid1;if(!valid5){const _errs44 = errors;if(!(data12 instanceof Function)){const err10 = {instancePath:instancePath+"/writeToDisk",schemaPath:"#/properties/writeToDisk/anyOf/1/instanceof",keyword:"instanceof",params:{},message:"must pass \"instanceof\" keyword validation"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}var _valid1 = _errs44 === errors;valid5 = valid5 || _valid1;}if(!valid5){const err11 = {instancePath:instancePath+"/writeToDisk",schemaPath:"#/properties/writeToDisk/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;validate10.errors = vErrors;return false;}else {errors = _errs41;if(vErrors !== null){if(_errs41){vErrors.length = _errs41;}else {vErrors = null;}}}var valid0 = _errs40 === errors;}else {var valid0 = true;}if(valid0){if(data.methods !== undefined){let data13 = data.methods;const _errs46 = errors;if(errors === _errs46){if(Array.isArray(data13)){var valid6 = true;const len0 = data13.length;for(let i0=0; i0=", limit: 1},message:"must be >= 1"};if(vErrors === null){vErrors = [err49];}else {vErrors.push(err49);}errors++;}}else {const err50 = {instancePath:instancePath+"/hot/heartbeat",schemaPath:"#/properties/hot/anyOf/1/properties/heartbeat/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err50];}else {vErrors.push(err50);}errors++;}}var valid16 = _errs137 === errors;}else {var valid16 = true;}if(valid16){if(data32.ws !== undefined){let data36 = data32.ws;const _errs139 = errors;if(errors === _errs139){if(data36 && typeof data36 == "object" && !Array.isArray(data36)){}else {const err51 = {instancePath:instancePath+"/hot/ws",schemaPath:"#/properties/hot/anyOf/1/properties/ws/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err51];}else {vErrors.push(err51);}errors++;}}var valid16 = _errs139 === errors;}else {var valid16 = true;}if(valid16){if(data32.progress !== undefined){const _errs143 = errors;if(typeof data32.progress !== "boolean"){const err52 = {instancePath:instancePath+"/hot/progress",schemaPath:"#/properties/hot/anyOf/1/properties/progress/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err52];}else {vErrors.push(err52);}errors++;}var valid16 = _errs143 === errors;}else {var valid16 = true;}if(valid16){if(data32.token !== undefined){let data38 = data32.token;const _errs145 = errors;const _errs146 = errors;let valid18 = false;const _errs147 = errors;if(typeof data38 !== "boolean"){const err53 = {instancePath:instancePath+"/hot/token",schemaPath:"#/properties/hot/anyOf/1/properties/token/anyOf/0/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err53];}else {vErrors.push(err53);}errors++;}var _valid9 = _errs147 === errors;valid18 = valid18 || _valid9;if(!valid18){const _errs149 = errors;if(errors === _errs149){if(typeof data38 === "string"){if(data38.length < 1){const err54 = {instancePath:instancePath+"/hot/token",schemaPath:"#/properties/hot/anyOf/1/properties/token/anyOf/1/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err54];}else {vErrors.push(err54);}errors++;}}else {const err55 = {instancePath:instancePath+"/hot/token",schemaPath:"#/properties/hot/anyOf/1/properties/token/anyOf/1/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err55];}else {vErrors.push(err55);}errors++;}}var _valid9 = _errs149 === errors;valid18 = valid18 || _valid9;}if(!valid18){const err56 = {instancePath:instancePath+"/hot/token",schemaPath:"#/properties/hot/anyOf/1/properties/token/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err56];}else {vErrors.push(err56);}errors++;}else {errors = _errs146;if(vErrors !== null){if(_errs146){vErrors.length = _errs146;}else {vErrors = null;}}}var valid16 = _errs145 === errors;}else {var valid16 = true;}if(valid16){if(data32.cors !== undefined){let data39 = data32.cors;const _errs152 = errors;const _errs153 = errors;let valid19 = false;const _errs154 = errors;if(typeof data39 !== "boolean"){const err57 = {instancePath:instancePath+"/hot/cors",schemaPath:"#/properties/hot/anyOf/1/properties/cors/anyOf/0/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err57];}else {vErrors.push(err57);}errors++;}var _valid10 = _errs154 === errors;valid19 = valid19 || _valid10;if(!valid19){const _errs156 = errors;const _errs158 = errors;let valid21 = false;const _errs159 = errors;if(errors === _errs159){if(typeof data39 === "string"){if(data39.length < 1){const err58 = {instancePath:instancePath+"/hot/cors",schemaPath:"#/definitions/CorsOrigin/anyOf/0/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err58];}else {vErrors.push(err58);}errors++;}}else {const err59 = {instancePath:instancePath+"/hot/cors",schemaPath:"#/definitions/CorsOrigin/anyOf/0/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err59];}else {vErrors.push(err59);}errors++;}}var _valid11 = _errs159 === errors;valid21 = valid21 || _valid11;if(!valid21){const _errs161 = errors;if(!(data39 instanceof RegExp)){const err60 = {instancePath:instancePath+"/hot/cors",schemaPath:"#/definitions/CorsOrigin/anyOf/1/instanceof",keyword:"instanceof",params:{},message:"must pass \"instanceof\" keyword validation"};if(vErrors === null){vErrors = [err60];}else {vErrors.push(err60);}errors++;}var _valid11 = _errs161 === errors;valid21 = valid21 || _valid11;if(!valid21){const _errs162 = errors;if(errors === _errs162){if(Array.isArray(data39)){if(data39.length < 1){const err61 = {instancePath:instancePath+"/hot/cors",schemaPath:"#/definitions/CorsOrigin/anyOf/2/minItems",keyword:"minItems",params:{limit: 1},message:"must NOT have fewer than 1 items"};if(vErrors === null){vErrors = [err61];}else {vErrors.push(err61);}errors++;}else {var valid22 = true;const len2 = data39.length;for(let i2=0; i2=", limit: 0},message:"must be >= 0"};if(vErrors === null){vErrors = [err121];}else {vErrors.push(err121);}errors++;}}else {const err122 = {instancePath:instancePath+"/hot/client/connect/retries",schemaPath:"#/definitions/HotClient/properties/connect/anyOf/1/properties/retries/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err122];}else {vErrors.push(err122);}errors++;}}var valid41 = _errs257 === errors;}else {var valid41 = true;}if(valid41){if(data58.timeout !== undefined){let data60 = data58.timeout;const _errs259 = errors;if(errors === _errs259){if(typeof data60 == "number"){if(data60 < 1 || isNaN(data60)){const err123 = {instancePath:instancePath+"/hot/client/connect/timeout",schemaPath:"#/definitions/HotClient/properties/connect/anyOf/1/properties/timeout/minimum",keyword:"minimum",params:{comparison: ">=", limit: 1},message:"must be >= 1"};if(vErrors === null){vErrors = [err123];}else {vErrors.push(err123);}errors++;}}else {const err124 = {instancePath:instancePath+"/hot/client/connect/timeout",schemaPath:"#/definitions/HotClient/properties/connect/anyOf/1/properties/timeout/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err124];}else {vErrors.push(err124);}errors++;}}var valid41 = _errs259 === errors;}else {var valid41 = true;}}}}else {const err125 = {instancePath:instancePath+"/hot/client/connect",schemaPath:"#/definitions/HotClient/properties/connect/anyOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err125];}else {vErrors.push(err125);}errors++;}}var _valid23 = _errs254 === errors;valid40 = valid40 || _valid23;}if(!valid40){const err126 = {instancePath:instancePath+"/hot/client/connect",schemaPath:"#/definitions/HotClient/properties/connect/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err126];}else {vErrors.push(err126);}errors++;}else {errors = _errs251;if(vErrors !== null){if(_errs251){vErrors.length = _errs251;}else {vErrors = null;}}}var valid32 = _errs250 === errors;}else {var valid32 = true;}if(valid32){if(data45.pageParamPrefix !== undefined){let data61 = data45.pageParamPrefix;const _errs261 = errors;if(errors === _errs261){if(typeof data61 === "string"){if(data61.length < 1){const err127 = {instancePath:instancePath+"/hot/client/pageParamPrefix",schemaPath:"#/definitions/HotClient/properties/pageParamPrefix/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err127];}else {vErrors.push(err127);}errors++;}}else {const err128 = {instancePath:instancePath+"/hot/client/pageParamPrefix",schemaPath:"#/definitions/HotClient/properties/pageParamPrefix/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err128];}else {vErrors.push(err128);}errors++;}}var valid32 = _errs261 === errors;}else {var valid32 = true;}if(valid32){if(data45.logging !== undefined){let data62 = data45.logging;const _errs263 = errors;const _errs264 = errors;let valid42 = false;const _errs265 = errors;if(!((((((data62 === "none") || (data62 === "error")) || (data62 === "warn")) || (data62 === "info")) || (data62 === "log")) || (data62 === "verbose"))){const err129 = {instancePath:instancePath+"/hot/client/logging",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/0/enum",keyword:"enum",params:{allowedValues: schema14.properties.logging.anyOf[0].enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err129];}else {vErrors.push(err129);}errors++;}var _valid24 = _errs265 === errors;valid42 = valid42 || _valid24;if(!valid42){const _errs266 = errors;if(errors === _errs266){if(data62 && typeof data62 == "object" && !Array.isArray(data62)){const _errs268 = errors;for(const key11 in data62){if(!((key11 === "level") || (key11 === "name"))){const err130 = {instancePath:instancePath+"/hot/client/logging",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/1/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key11},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err130];}else {vErrors.push(err130);}errors++;break;}}if(_errs268 === errors){if(data62.level !== undefined){let data63 = data62.level;const _errs269 = errors;if(!((((((data63 === "none") || (data63 === "error")) || (data63 === "warn")) || (data63 === "info")) || (data63 === "log")) || (data63 === "verbose"))){const err131 = {instancePath:instancePath+"/hot/client/logging/level",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/1/properties/level/enum",keyword:"enum",params:{allowedValues: schema14.properties.logging.anyOf[1].properties.level.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err131];}else {vErrors.push(err131);}errors++;}var valid43 = _errs269 === errors;}else {var valid43 = true;}if(valid43){if(data62.name !== undefined){let data64 = data62.name;const _errs270 = errors;if(errors === _errs270){if(typeof data64 === "string"){if(data64.length < 1){const err132 = {instancePath:instancePath+"/hot/client/logging/name",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/1/properties/name/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err132];}else {vErrors.push(err132);}errors++;}}else {const err133 = {instancePath:instancePath+"/hot/client/logging/name",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/1/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err133];}else {vErrors.push(err133);}errors++;}}var valid43 = _errs270 === errors;}else {var valid43 = true;}}}}else {const err134 = {instancePath:instancePath+"/hot/client/logging",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err134];}else {vErrors.push(err134);}errors++;}}var _valid24 = _errs266 === errors;valid42 = valid42 || _valid24;}if(!valid42){const err135 = {instancePath:instancePath+"/hot/client/logging",schemaPath:"#/definitions/HotClient/properties/logging/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err135];}else {vErrors.push(err135);}errors++;}else {errors = _errs264;if(vErrors !== null){if(_errs264){vErrors.length = _errs264;}else {vErrors = null;}}}var valid32 = _errs263 === errors;}else {var valid32 = true;}if(valid32){if(data45.dynamicPublicPath !== undefined){const _errs272 = errors;if(typeof data45.dynamicPublicPath !== "boolean"){const err136 = {instancePath:instancePath+"/hot/client/dynamicPublicPath",schemaPath:"#/definitions/HotClient/properties/dynamicPublicPath/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err136];}else {vErrors.push(err136);}errors++;}var valid32 = _errs272 === errors;}else {var valid32 = true;}}}}}}}}}}}}else {const err137 = {instancePath:instancePath+"/hot/client",schemaPath:"#/definitions/HotClient/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err137];}else {vErrors.push(err137);}errors++;}}var _valid16 = _errs201 === errors;valid30 = valid30 || _valid16;}if(!valid30){const err138 = {instancePath:instancePath+"/hot/client",schemaPath:"#/properties/hot/anyOf/1/properties/client/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err138];}else {vErrors.push(err138);}errors++;}else {errors = _errs199;if(vErrors !== null){if(_errs199){vErrors.length = _errs199;}else {vErrors = null;}}}var valid16 = _errs198 === errors;}else {var valid16 = true;}}}}}}}}}}}}else {const err139 = {instancePath:instancePath+"/hot",schemaPath:"#/properties/hot/anyOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err139];}else {vErrors.push(err139);}errors++;}}var _valid7 = _errs128 === errors;valid15 = valid15 || _valid7;}if(!valid15){const err140 = {instancePath:instancePath+"/hot",schemaPath:"#/properties/hot/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err140];}else {vErrors.push(err140);}errors++;validate10.errors = vErrors;return false;}else {errors = _errs125;if(vErrors !== null){if(_errs125){vErrors.length = _errs125;}else {vErrors = null;}}}var valid0 = _errs124 === errors;}else {var valid0 = true;}}}}}}}}}}}}}}}}}}}}}else {validate10.errors = [{instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}validate10.errors = vErrors;return errors === 0;} \ No newline at end of file +"use strict";module.exports = validate10;module.exports.default = validate10;const schema11 = {"definitions":{"HotClient":{"description":"Options handed to the browser runtime through its entry query.","type":"object","additionalProperties":false,"properties":{"transport":{"description":"Which transport the runtime speaks: `sse` or `ws`, or a module that exports a client class of your own, which is used in place of the built-in one. Defaults to the resolved `hot.transport`.","anyOf":[{"enum":["sse","ws"]},{"type":"string","minLength":1}]},"url":{"description":"Where the runtime connects: a path, an absolute url for an endpoint reached on another origin or through a proxy, or the parts of one that differ, with the rest resolved in the page, which is the only place the rest is known. Defaults to the resolved `hot.path`.","anyOf":[{"type":"string","minLength":1},{"type":"object","additionalProperties":false,"properties":{"protocol":{"description":"The scheme the runtime connects over. Unset, or `auto`, follows the page — and a page served over TLS then gets a secure connection, because a browser refuses a plaintext one from it. Set explicitly, it is honoured as given; the one exception is a `hostname` naming every interface, which is resolved to the page's host and takes the page's scheme with it. Only whether the scheme is the secure one carries over, since the two transports do not share one.","anyOf":[{"enum":["auto"]},{"type":"string","minLength":1}]},"hostname":{"description":"The host the runtime connects to. An address a server listens on to mean every interface (`0.0.0.0`, `::`) is not somewhere a page can connect, so it resolves to the page's own host.","type":"string","minLength":1},"port":{"description":"The port the runtime connects to. `0` means a port the server picked, which resolves to the page's own.","anyOf":[{"type":"number"},{"type":"string","minLength":1}]},"pathname":{"description":"The path the runtime connects to. Defaults to the resolved `hot.path`.","type":"string"},"username":{"description":"The username the runtime authenticates with.","type":"string"},"password":{"description":"The password the runtime authenticates with. Sent only alongside a username, since basic authentication has no empty one.","type":"string"}}}]},"name":{"description":"Limit the runtime to one compilation's builds. Defaults to the compilation's own name.","type":"string"},"overlay":{"description":"Show build problems and uncaught runtime errors in an overlay.","anyOf":[{"type":"boolean"},{"type":"object"}]},"progress":{"description":"Show an indicator while a rebuild is in progress.","anyOf":[{"type":"boolean"},{"enum":["circular","linear"]}]},"apply":{"description":"What a build does to the page: `hmr` applies the update and reloads if it cannot be applied, `hmr-only` applies it and stops with a message if it cannot, `reload` loads the page again on a build that changed something, and `nothing` leaves the page alone until you reload it.","enum":["hmr","hmr-only","reload","nothing"]},"connect":{"description":"Whether to connect when the entry runs, and how the connection is held open. `false` does not connect; an object sets `retries` and `timeout`.","anyOf":[{"type":"boolean"},{"type":"object","additionalProperties":false,"properties":{"retries":{"description":"How many times to reconnect before giving up. Server-Sent Events keep trying for as long as the page is open unless this is set, since a dev server is expected to come back.","type":"number","minimum":0},"timeout":{"description":"How long silence is tolerated before reconnecting, in milliseconds. Server-Sent Events only: their heartbeat arrives as data the client can see, whereas a WebSocket's is a protocol ping the browser answers without telling JavaScript.","type":"number","minimum":1}}}]},"pageParamPrefix":{"description":"Prefix of the page-url parameters that override `apply` for a single page, as in `?webpack-dev-middleware-hot=false`.","type":"string","minLength":1},"logging":{"description":"Logger level in the browser, or an object carrying the level and the name every message is labelled with in the console — a package embedding this runtime is the one a developer would report a problem to, so it can say its own name.","anyOf":[{"enum":["none","error","warn","info","log","verbose"]},{"type":"object","additionalProperties":false,"properties":{"level":{"enum":["none","error","warn","info","log","verbose"]},"name":{"description":"What every message is labelled with in the console. Defaults to this package's name.","type":"string","minLength":1}}}]},"dynamicPublicPath":{"description":"Prefix the endpoint path with the bundle's public path at runtime.","type":"boolean"}}},"CorsOrigin":{"description":"An origin, written as a browser sends it (scheme, host and port, no trailing slash), several of them, a pattern, or a function asked about each.","anyOf":[{"type":"string","minLength":1},{"instanceof":"RegExp"},{"type":"array","items":{"anyOf":[{"type":"string","minLength":1},{"instanceof":"RegExp"}]},"minItems":1},{"instanceof":"Function"}]}},"type":"object","properties":{"cache":{"description":"How responses are cached.","link":"https://github.com/webpack/webpack-dev-middleware#cache","type":"object","additionalProperties":false,"properties":{"etag":{"description":"Enable or disable etag generation.","enum":["weak","strong"]},"lastModified":{"description":"Enable or disable `Last-Modified` header. Uses the file system's last modified value.","type":"boolean"},"control":{"description":"Enable or disable setting `Cache-Control` response header.","anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string","minLength":1},{"type":"object","properties":{"maxAge":{"type":"number"},"immutable":{"type":"boolean"}},"additionalProperties":false}]},"immutable":{"description":"Enable or disable setting `Cache-Control: public, max-age=31536000, immutable` response header for immutable assets (i.e. asset with a hash in file name like `image.a4c12bde.jpg`).","type":"boolean"}}},"mime":{"description":"How a file's media type is decided.","link":"https://github.com/webpack/webpack-dev-middleware#mime","type":"object","additionalProperties":false,"properties":{"types":{"description":"Allows a user to register custom mime types or extension mappings.","type":"object"},"default":{"description":"Allows a user to register a default mime type when we can't determine the content type.","type":"string"}}},"mimeTypes":{"description":"Allows a user to register custom mime types or extension mappings.","link":"https://github.com/webpack/webpack-dev-middleware#mimetypes","type":"object"},"mimeTypeDefault":{"description":"Allows a user to register a default mime type when we can't determine the content type.","link":"https://github.com/webpack/webpack-dev-middleware#mimetypedefault","type":"string"},"writeToDisk":{"description":"Allows to write generated files on disk.","link":"https://github.com/webpack/webpack-dev-middleware#writetodisk","anyOf":[{"type":"boolean"},{"instanceof":"Function"}]},"methods":{"description":"Allows to pass the list of HTTP request methods accepted by the middleware.","link":"https://github.com/webpack/webpack-dev-middleware#methods","type":"array","items":{"type":"string","minLength":1}},"headers":{"anyOf":[{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"key":{"description":"key of header.","type":"string"},"value":{"description":"value of header.","type":"string"}}},"minItems":1},{"type":"object"},{"instanceof":"Function"}],"description":"Allows to pass custom HTTP headers on each request","link":"https://github.com/webpack/webpack-dev-middleware#headers"},"publicPath":{"description":"The `publicPath` specifies the public URL address of the output files when referenced in a browser.","link":"https://github.com/webpack/webpack-dev-middleware#publicpath","anyOf":[{"enum":["auto"]},{"type":"string"},{"instanceof":"Function"}]},"stats":{"description":"Stats options object or preset name.","link":"https://github.com/webpack/webpack-dev-middleware#stats","anyOf":[{"enum":["none","summary","errors-only","errors-warnings","minimal","normal","detailed","verbose"]},{"type":"boolean"},{"type":"object","additionalProperties":true}]},"serverSideRender":{"description":"Instructs the module to enable or disable the server-side rendering mode.","link":"https://github.com/webpack/webpack-dev-middleware#serversiderender","type":"boolean"},"outputFileSystem":{"description":"Set the default file system which will be used by webpack as primary destination of generated files.","link":"https://github.com/webpack/webpack-dev-middleware#outputfilesystem","type":"object"},"index":{"description":"Allows to serve an index of the directory.","link":"https://github.com/webpack/webpack-dev-middleware#index","anyOf":[{"type":"boolean"},{"type":"string","minLength":1}]},"modifyResponseData":{"description":"Allows to set up a callback to change the response data.","link":"https://github.com/webpack/webpack-dev-middleware#modifyresponsedata","instanceof":"Function"},"etag":{"description":"Enable or disable etag generation.","link":"https://github.com/webpack/webpack-dev-middleware#etag","enum":["weak","strong"]},"lastModified":{"description":"Enable or disable `Last-Modified` header. Uses the file system's last modified value.","link":"https://github.com/webpack/webpack-dev-middleware#lastmodified","type":"boolean"},"cacheControl":{"description":"Enable or disable setting `Cache-Control` response header.","link":"https://github.com/webpack/webpack-dev-middleware#cachecontrol","anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string","minLength":1},{"type":"object","properties":{"maxAge":{"type":"number"},"immutable":{"type":"boolean"}},"additionalProperties":false}]},"cacheImmutable":{"description":"Enable or disable setting `Cache-Control: public, max-age=31536000, immutable` response header for immutable assets (i.e. asset with a hash in file name like `image.a4c12bde.jpg`).","link":"https://github.com/webpack/webpack-dev-middleware#cacheimmutable","type":"boolean"},"forwardError":{"description":"Enable or disable forwarding errors to next middleware.","link":"https://github.com/webpack/webpack-dev-middleware#forwarderrors","type":"boolean"},"hot":{"description":"Enable hot module replacement over a Server-Sent Events or WebSocket endpoint.","link":"https://github.com/webpack/webpack-dev-middleware#hot","anyOf":[{"type":"boolean"},{"type":"object","additionalProperties":false,"properties":{"transport":{"description":"How events reach the clients: `sse`, `ws` (needs the optional `ws` dependency and the upgrades of an HTTP server: hand the server to the middleware's `attach(server)`, or pass each upgrade to `handleUpgrade(req, socket, head)`), or a function building a transport of your own.","anyOf":[{"enum":["sse","ws"]},{"instanceof":"Function"}]},"path":{"description":"The path the endpoint is served at. Must start with a slash and carry no query string or fragment.","type":"string","pattern":"^/[^?#]*$"},"heartbeat":{"description":"Heartbeat interval (in milliseconds) used to keep the connection alive.","type":"number","minimum":1},"ws":{"description":"Options for the `ws` server behind the `ws` transport: compression, payload limits, `verifyClient`, or a `port` or a `server` of its own to listen on instead of answering the upgrades it is handed. `path`, `noServer` and `clientTracking` are the middleware's and are ignored here.","link":"https://github.com/webpack/webpack-dev-middleware#hot","type":"object","additionalProperties":true},"progress":{"description":"Publish compilation progress events to the clients.","type":"boolean"},"token":{"description":"A secret the injected client carries and the endpoint requires, so reaching the stream takes something a page has to have been given rather than a header the browser may not send. `true` mints one per run, a string uses that one — for a client of your own that has to build the url itself — and `false` requires none. Defaults to `false`, because requiring one would refuse a client this middleware did not inject; `true` in the next major release.","link":"https://github.com/webpack/webpack-dev-middleware#hottoken","anyOf":[{"type":"boolean"},{"type":"string","minLength":1}]},"cors":{"description":"Which origins may read the Server-Sent Events endpoint from a page on another one. Local origins only by default. `true` grants every origin, which lets any site the developer has open read the build's errors, including the source frames webpack puts in them.","link":"https://github.com/webpack/webpack-dev-middleware#hotcors","anyOf":[{"type":"boolean"},{"$ref":"#/definitions/CorsOrigin"},{"type":"object","additionalProperties":false,"properties":{"origin":{"description":"Which origins may read it, as Vite and `expressjs/cors` are configured.","anyOf":[{"type":"boolean"},{"$ref":"#/definitions/CorsOrigin"}]}}}]},"statsOptions":{"description":"Deprecated, do not use, will be removed in the next major release. Use the `stats` option instead, which decides whether a payload carries errors and warnings.","type":"object","additionalProperties":true},"inject":{"description":"What is added to the compilation: `all` (the default) adds the runtime — this package's client and overlay — and HotModuleReplacementPlugin; `plugin` adds only the plugin, for a page that wires a client of its own; `client` adds only the runtime, for a configuration that applies the plugin itself; `none` adds nothing.","link":"https://github.com/webpack/webpack-dev-middleware#hotinject","enum":["all","plugin","client","none"]},"client":{"description":"Options handed to the browser runtime through its entry query.","link":"https://github.com/webpack/webpack-dev-middleware#hot","$ref":"#/definitions/HotClient"}}}]}},"additionalProperties":false};const schema12 = {"description":"An origin, written as a browser sends it (scheme, host and port, no trailing slash), several of them, a pattern, or a function asked about each.","anyOf":[{"type":"string","minLength":1},{"instanceof":"RegExp"},{"type":"array","items":{"anyOf":[{"type":"string","minLength":1},{"instanceof":"RegExp"}]},"minItems":1},{"instanceof":"Function"}]};const schema14 = {"description":"Options handed to the browser runtime through its entry query.","type":"object","additionalProperties":false,"properties":{"transport":{"description":"Which transport the runtime speaks: `sse` or `ws`, or a module that exports a client class of your own, which is used in place of the built-in one. Defaults to the resolved `hot.transport`.","anyOf":[{"enum":["sse","ws"]},{"type":"string","minLength":1}]},"url":{"description":"Where the runtime connects: a path, an absolute url for an endpoint reached on another origin or through a proxy, or the parts of one that differ, with the rest resolved in the page, which is the only place the rest is known. Defaults to the resolved `hot.path`.","anyOf":[{"type":"string","minLength":1},{"type":"object","additionalProperties":false,"properties":{"protocol":{"description":"The scheme the runtime connects over. Unset, or `auto`, follows the page — and a page served over TLS then gets a secure connection, because a browser refuses a plaintext one from it. Set explicitly, it is honoured as given; the one exception is a `hostname` naming every interface, which is resolved to the page's host and takes the page's scheme with it. Only whether the scheme is the secure one carries over, since the two transports do not share one.","anyOf":[{"enum":["auto"]},{"type":"string","minLength":1}]},"hostname":{"description":"The host the runtime connects to. An address a server listens on to mean every interface (`0.0.0.0`, `::`) is not somewhere a page can connect, so it resolves to the page's own host.","type":"string","minLength":1},"port":{"description":"The port the runtime connects to. `0` means a port the server picked, which resolves to the page's own.","anyOf":[{"type":"number"},{"type":"string","minLength":1}]},"pathname":{"description":"The path the runtime connects to. Defaults to the resolved `hot.path`.","type":"string"},"username":{"description":"The username the runtime authenticates with.","type":"string"},"password":{"description":"The password the runtime authenticates with. Sent only alongside a username, since basic authentication has no empty one.","type":"string"}}}]},"name":{"description":"Limit the runtime to one compilation's builds. Defaults to the compilation's own name.","type":"string"},"overlay":{"description":"Show build problems and uncaught runtime errors in an overlay.","anyOf":[{"type":"boolean"},{"type":"object"}]},"progress":{"description":"Show an indicator while a rebuild is in progress.","anyOf":[{"type":"boolean"},{"enum":["circular","linear"]}]},"apply":{"description":"What a build does to the page: `hmr` applies the update and reloads if it cannot be applied, `hmr-only` applies it and stops with a message if it cannot, `reload` loads the page again on a build that changed something, and `nothing` leaves the page alone until you reload it.","enum":["hmr","hmr-only","reload","nothing"]},"connect":{"description":"Whether to connect when the entry runs, and how the connection is held open. `false` does not connect; an object sets `retries` and `timeout`.","anyOf":[{"type":"boolean"},{"type":"object","additionalProperties":false,"properties":{"retries":{"description":"How many times to reconnect before giving up. Server-Sent Events keep trying for as long as the page is open unless this is set, since a dev server is expected to come back.","type":"number","minimum":0},"timeout":{"description":"How long silence is tolerated before reconnecting, in milliseconds. Server-Sent Events only: their heartbeat arrives as data the client can see, whereas a WebSocket's is a protocol ping the browser answers without telling JavaScript.","type":"number","minimum":1}}}]},"pageParamPrefix":{"description":"Prefix of the page-url parameters that override `apply` for a single page, as in `?webpack-dev-middleware-hot=false`.","type":"string","minLength":1},"logging":{"description":"Logger level in the browser, or an object carrying the level and the name every message is labelled with in the console — a package embedding this runtime is the one a developer would report a problem to, so it can say its own name.","anyOf":[{"enum":["none","error","warn","info","log","verbose"]},{"type":"object","additionalProperties":false,"properties":{"level":{"enum":["none","error","warn","info","log","verbose"]},"name":{"description":"What every message is labelled with in the console. Defaults to this package's name.","type":"string","minLength":1}}}]},"dynamicPublicPath":{"description":"Prefix the endpoint path with the bundle's public path at runtime.","type":"boolean"}}};const func2 = Object.prototype.hasOwnProperty;const pattern0 = new RegExp("^/[^?#]*$", "u");function validate10(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){let vErrors = null;let errors = 0;if(errors === 0){if(data && typeof data == "object" && !Array.isArray(data)){const _errs1 = errors;for(const key0 in data){if(!(func2.call(schema11.properties, key0))){validate10.errors = [{instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}];return false;break;}}if(_errs1 === errors){if(data.cache !== undefined){let data0 = data.cache;const _errs2 = errors;if(errors === _errs2){if(data0 && typeof data0 == "object" && !Array.isArray(data0)){const _errs5 = errors;for(const key1 in data0){if(!((((key1 === "etag") || (key1 === "lastModified")) || (key1 === "control")) || (key1 === "immutable"))){validate10.errors = [{instancePath:instancePath+"/cache",schemaPath:"#/properties/cache/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}];return false;break;}}if(_errs5 === errors){if(data0.etag !== undefined){let data1 = data0.etag;const _errs6 = errors;if(!((data1 === "weak") || (data1 === "strong"))){validate10.errors = [{instancePath:instancePath+"/cache/etag",schemaPath:"#/properties/cache/properties/etag/enum",keyword:"enum",params:{allowedValues: schema11.properties.cache.properties.etag.enum},message:"must be equal to one of the allowed values"}];return false;}var valid1 = _errs6 === errors;}else {var valid1 = true;}if(valid1){if(data0.lastModified !== undefined){const _errs7 = errors;if(typeof data0.lastModified !== "boolean"){validate10.errors = [{instancePath:instancePath+"/cache/lastModified",schemaPath:"#/properties/cache/properties/lastModified/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}];return false;}var valid1 = _errs7 === errors;}else {var valid1 = true;}if(valid1){if(data0.control !== undefined){let data3 = data0.control;const _errs9 = errors;const _errs10 = errors;let valid2 = false;const _errs11 = errors;if(typeof data3 !== "boolean"){const err0 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/0/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}var _valid0 = _errs11 === errors;valid2 = valid2 || _valid0;if(!valid2){const _errs13 = errors;if(!(typeof data3 == "number")){const err1 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/1/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}var _valid0 = _errs13 === errors;valid2 = valid2 || _valid0;if(!valid2){const _errs15 = errors;if(errors === _errs15){if(typeof data3 === "string"){if(data3.length < 1){const err2 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/2/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}}else {const err3 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/2/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}}var _valid0 = _errs15 === errors;valid2 = valid2 || _valid0;if(!valid2){const _errs17 = errors;if(errors === _errs17){if(data3 && typeof data3 == "object" && !Array.isArray(data3)){const _errs19 = errors;for(const key2 in data3){if(!((key2 === "maxAge") || (key2 === "immutable"))){const err4 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/3/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;break;}}if(_errs19 === errors){if(data3.maxAge !== undefined){const _errs20 = errors;if(!(typeof data3.maxAge == "number")){const err5 = {instancePath:instancePath+"/cache/control/maxAge",schemaPath:"#/properties/cache/properties/control/anyOf/3/properties/maxAge/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}var valid3 = _errs20 === errors;}else {var valid3 = true;}if(valid3){if(data3.immutable !== undefined){const _errs22 = errors;if(typeof data3.immutable !== "boolean"){const err6 = {instancePath:instancePath+"/cache/control/immutable",schemaPath:"#/properties/cache/properties/control/anyOf/3/properties/immutable/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}var valid3 = _errs22 === errors;}else {var valid3 = true;}}}}else {const err7 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf/3/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}}var _valid0 = _errs17 === errors;valid2 = valid2 || _valid0;}}}if(!valid2){const err8 = {instancePath:instancePath+"/cache/control",schemaPath:"#/properties/cache/properties/control/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;validate10.errors = vErrors;return false;}else {errors = _errs10;if(vErrors !== null){if(_errs10){vErrors.length = _errs10;}else {vErrors = null;}}}var valid1 = _errs9 === errors;}else {var valid1 = true;}if(valid1){if(data0.immutable !== undefined){const _errs24 = errors;if(typeof data0.immutable !== "boolean"){validate10.errors = [{instancePath:instancePath+"/cache/immutable",schemaPath:"#/properties/cache/properties/immutable/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}];return false;}var valid1 = _errs24 === errors;}else {var valid1 = true;}}}}}}else {validate10.errors = [{instancePath:instancePath+"/cache",schemaPath:"#/properties/cache/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid0 = _errs2 === errors;}else {var valid0 = true;}if(valid0){if(data.mime !== undefined){let data7 = data.mime;const _errs26 = errors;if(errors === _errs26){if(data7 && typeof data7 == "object" && !Array.isArray(data7)){const _errs29 = errors;for(const key3 in data7){if(!((key3 === "types") || (key3 === "default"))){validate10.errors = [{instancePath:instancePath+"/mime",schemaPath:"#/properties/mime/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}];return false;break;}}if(_errs29 === errors){if(data7.types !== undefined){let data8 = data7.types;const _errs30 = errors;if(!(data8 && typeof data8 == "object" && !Array.isArray(data8))){validate10.errors = [{instancePath:instancePath+"/mime/types",schemaPath:"#/properties/mime/properties/types/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}var valid4 = _errs30 === errors;}else {var valid4 = true;}if(valid4){if(data7.default !== undefined){const _errs32 = errors;if(typeof data7.default !== "string"){validate10.errors = [{instancePath:instancePath+"/mime/default",schemaPath:"#/properties/mime/properties/default/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}var valid4 = _errs32 === errors;}else {var valid4 = true;}}}}else {validate10.errors = [{instancePath:instancePath+"/mime",schemaPath:"#/properties/mime/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid0 = _errs26 === errors;}else {var valid0 = true;}if(valid0){if(data.mimeTypes !== undefined){let data10 = data.mimeTypes;const _errs34 = errors;if(!(data10 && typeof data10 == "object" && !Array.isArray(data10))){validate10.errors = [{instancePath:instancePath+"/mimeTypes",schemaPath:"#/properties/mimeTypes/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}var valid0 = _errs34 === errors;}else {var valid0 = true;}if(valid0){if(data.mimeTypeDefault !== undefined){const _errs37 = errors;if(typeof data.mimeTypeDefault !== "string"){validate10.errors = [{instancePath:instancePath+"/mimeTypeDefault",schemaPath:"#/properties/mimeTypeDefault/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}var valid0 = _errs37 === errors;}else {var valid0 = true;}if(valid0){if(data.writeToDisk !== undefined){let data12 = data.writeToDisk;const _errs40 = errors;const _errs41 = errors;let valid5 = false;const _errs42 = errors;if(typeof data12 !== "boolean"){const err9 = {instancePath:instancePath+"/writeToDisk",schemaPath:"#/properties/writeToDisk/anyOf/0/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}var _valid1 = _errs42 === errors;valid5 = valid5 || _valid1;if(!valid5){const _errs44 = errors;if(!(data12 instanceof Function)){const err10 = {instancePath:instancePath+"/writeToDisk",schemaPath:"#/properties/writeToDisk/anyOf/1/instanceof",keyword:"instanceof",params:{},message:"must pass \"instanceof\" keyword validation"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}var _valid1 = _errs44 === errors;valid5 = valid5 || _valid1;}if(!valid5){const err11 = {instancePath:instancePath+"/writeToDisk",schemaPath:"#/properties/writeToDisk/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;validate10.errors = vErrors;return false;}else {errors = _errs41;if(vErrors !== null){if(_errs41){vErrors.length = _errs41;}else {vErrors = null;}}}var valid0 = _errs40 === errors;}else {var valid0 = true;}if(valid0){if(data.methods !== undefined){let data13 = data.methods;const _errs46 = errors;if(errors === _errs46){if(Array.isArray(data13)){var valid6 = true;const len0 = data13.length;for(let i0=0; i0=", limit: 1},message:"must be >= 1"};if(vErrors === null){vErrors = [err49];}else {vErrors.push(err49);}errors++;}}else {const err50 = {instancePath:instancePath+"/hot/heartbeat",schemaPath:"#/properties/hot/anyOf/1/properties/heartbeat/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err50];}else {vErrors.push(err50);}errors++;}}var valid16 = _errs137 === errors;}else {var valid16 = true;}if(valid16){if(data32.ws !== undefined){let data36 = data32.ws;const _errs139 = errors;if(errors === _errs139){if(data36 && typeof data36 == "object" && !Array.isArray(data36)){}else {const err51 = {instancePath:instancePath+"/hot/ws",schemaPath:"#/properties/hot/anyOf/1/properties/ws/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err51];}else {vErrors.push(err51);}errors++;}}var valid16 = _errs139 === errors;}else {var valid16 = true;}if(valid16){if(data32.progress !== undefined){const _errs143 = errors;if(typeof data32.progress !== "boolean"){const err52 = {instancePath:instancePath+"/hot/progress",schemaPath:"#/properties/hot/anyOf/1/properties/progress/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err52];}else {vErrors.push(err52);}errors++;}var valid16 = _errs143 === errors;}else {var valid16 = true;}if(valid16){if(data32.token !== undefined){let data38 = data32.token;const _errs145 = errors;const _errs146 = errors;let valid18 = false;const _errs147 = errors;if(typeof data38 !== "boolean"){const err53 = {instancePath:instancePath+"/hot/token",schemaPath:"#/properties/hot/anyOf/1/properties/token/anyOf/0/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err53];}else {vErrors.push(err53);}errors++;}var _valid9 = _errs147 === errors;valid18 = valid18 || _valid9;if(!valid18){const _errs149 = errors;if(errors === _errs149){if(typeof data38 === "string"){if(data38.length < 1){const err54 = {instancePath:instancePath+"/hot/token",schemaPath:"#/properties/hot/anyOf/1/properties/token/anyOf/1/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err54];}else {vErrors.push(err54);}errors++;}}else {const err55 = {instancePath:instancePath+"/hot/token",schemaPath:"#/properties/hot/anyOf/1/properties/token/anyOf/1/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err55];}else {vErrors.push(err55);}errors++;}}var _valid9 = _errs149 === errors;valid18 = valid18 || _valid9;}if(!valid18){const err56 = {instancePath:instancePath+"/hot/token",schemaPath:"#/properties/hot/anyOf/1/properties/token/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err56];}else {vErrors.push(err56);}errors++;}else {errors = _errs146;if(vErrors !== null){if(_errs146){vErrors.length = _errs146;}else {vErrors = null;}}}var valid16 = _errs145 === errors;}else {var valid16 = true;}if(valid16){if(data32.cors !== undefined){let data39 = data32.cors;const _errs152 = errors;const _errs153 = errors;let valid19 = false;const _errs154 = errors;if(typeof data39 !== "boolean"){const err57 = {instancePath:instancePath+"/hot/cors",schemaPath:"#/properties/hot/anyOf/1/properties/cors/anyOf/0/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err57];}else {vErrors.push(err57);}errors++;}var _valid10 = _errs154 === errors;valid19 = valid19 || _valid10;if(!valid19){const _errs156 = errors;const _errs158 = errors;let valid21 = false;const _errs159 = errors;if(errors === _errs159){if(typeof data39 === "string"){if(data39.length < 1){const err58 = {instancePath:instancePath+"/hot/cors",schemaPath:"#/definitions/CorsOrigin/anyOf/0/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err58];}else {vErrors.push(err58);}errors++;}}else {const err59 = {instancePath:instancePath+"/hot/cors",schemaPath:"#/definitions/CorsOrigin/anyOf/0/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err59];}else {vErrors.push(err59);}errors++;}}var _valid11 = _errs159 === errors;valid21 = valid21 || _valid11;if(!valid21){const _errs161 = errors;if(!(data39 instanceof RegExp)){const err60 = {instancePath:instancePath+"/hot/cors",schemaPath:"#/definitions/CorsOrigin/anyOf/1/instanceof",keyword:"instanceof",params:{},message:"must pass \"instanceof\" keyword validation"};if(vErrors === null){vErrors = [err60];}else {vErrors.push(err60);}errors++;}var _valid11 = _errs161 === errors;valid21 = valid21 || _valid11;if(!valid21){const _errs162 = errors;if(errors === _errs162){if(Array.isArray(data39)){if(data39.length < 1){const err61 = {instancePath:instancePath+"/hot/cors",schemaPath:"#/definitions/CorsOrigin/anyOf/2/minItems",keyword:"minItems",params:{limit: 1},message:"must NOT have fewer than 1 items"};if(vErrors === null){vErrors = [err61];}else {vErrors.push(err61);}errors++;}else {var valid22 = true;const len2 = data39.length;for(let i2=0; i2=", limit: 0},message:"must be >= 0"};if(vErrors === null){vErrors = [err120];}else {vErrors.push(err120);}errors++;}}else {const err121 = {instancePath:instancePath+"/hot/client/connect/retries",schemaPath:"#/definitions/HotClient/properties/connect/anyOf/1/properties/retries/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err121];}else {vErrors.push(err121);}errors++;}}var valid40 = _errs253 === errors;}else {var valid40 = true;}if(valid40){if(data58.timeout !== undefined){let data60 = data58.timeout;const _errs255 = errors;if(errors === _errs255){if(typeof data60 == "number"){if(data60 < 1 || isNaN(data60)){const err122 = {instancePath:instancePath+"/hot/client/connect/timeout",schemaPath:"#/definitions/HotClient/properties/connect/anyOf/1/properties/timeout/minimum",keyword:"minimum",params:{comparison: ">=", limit: 1},message:"must be >= 1"};if(vErrors === null){vErrors = [err122];}else {vErrors.push(err122);}errors++;}}else {const err123 = {instancePath:instancePath+"/hot/client/connect/timeout",schemaPath:"#/definitions/HotClient/properties/connect/anyOf/1/properties/timeout/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err123];}else {vErrors.push(err123);}errors++;}}var valid40 = _errs255 === errors;}else {var valid40 = true;}}}}else {const err124 = {instancePath:instancePath+"/hot/client/connect",schemaPath:"#/definitions/HotClient/properties/connect/anyOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err124];}else {vErrors.push(err124);}errors++;}}var _valid22 = _errs250 === errors;valid39 = valid39 || _valid22;}if(!valid39){const err125 = {instancePath:instancePath+"/hot/client/connect",schemaPath:"#/definitions/HotClient/properties/connect/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err125];}else {vErrors.push(err125);}errors++;}else {errors = _errs247;if(vErrors !== null){if(_errs247){vErrors.length = _errs247;}else {vErrors = null;}}}var valid31 = _errs246 === errors;}else {var valid31 = true;}if(valid31){if(data45.pageParamPrefix !== undefined){let data61 = data45.pageParamPrefix;const _errs257 = errors;if(errors === _errs257){if(typeof data61 === "string"){if(data61.length < 1){const err126 = {instancePath:instancePath+"/hot/client/pageParamPrefix",schemaPath:"#/definitions/HotClient/properties/pageParamPrefix/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err126];}else {vErrors.push(err126);}errors++;}}else {const err127 = {instancePath:instancePath+"/hot/client/pageParamPrefix",schemaPath:"#/definitions/HotClient/properties/pageParamPrefix/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err127];}else {vErrors.push(err127);}errors++;}}var valid31 = _errs257 === errors;}else {var valid31 = true;}if(valid31){if(data45.logging !== undefined){let data62 = data45.logging;const _errs259 = errors;const _errs260 = errors;let valid41 = false;const _errs261 = errors;if(!((((((data62 === "none") || (data62 === "error")) || (data62 === "warn")) || (data62 === "info")) || (data62 === "log")) || (data62 === "verbose"))){const err128 = {instancePath:instancePath+"/hot/client/logging",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/0/enum",keyword:"enum",params:{allowedValues: schema14.properties.logging.anyOf[0].enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err128];}else {vErrors.push(err128);}errors++;}var _valid23 = _errs261 === errors;valid41 = valid41 || _valid23;if(!valid41){const _errs262 = errors;if(errors === _errs262){if(data62 && typeof data62 == "object" && !Array.isArray(data62)){const _errs264 = errors;for(const key11 in data62){if(!((key11 === "level") || (key11 === "name"))){const err129 = {instancePath:instancePath+"/hot/client/logging",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/1/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key11},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err129];}else {vErrors.push(err129);}errors++;break;}}if(_errs264 === errors){if(data62.level !== undefined){let data63 = data62.level;const _errs265 = errors;if(!((((((data63 === "none") || (data63 === "error")) || (data63 === "warn")) || (data63 === "info")) || (data63 === "log")) || (data63 === "verbose"))){const err130 = {instancePath:instancePath+"/hot/client/logging/level",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/1/properties/level/enum",keyword:"enum",params:{allowedValues: schema14.properties.logging.anyOf[1].properties.level.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err130];}else {vErrors.push(err130);}errors++;}var valid42 = _errs265 === errors;}else {var valid42 = true;}if(valid42){if(data62.name !== undefined){let data64 = data62.name;const _errs266 = errors;if(errors === _errs266){if(typeof data64 === "string"){if(data64.length < 1){const err131 = {instancePath:instancePath+"/hot/client/logging/name",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/1/properties/name/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err131];}else {vErrors.push(err131);}errors++;}}else {const err132 = {instancePath:instancePath+"/hot/client/logging/name",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/1/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err132];}else {vErrors.push(err132);}errors++;}}var valid42 = _errs266 === errors;}else {var valid42 = true;}}}}else {const err133 = {instancePath:instancePath+"/hot/client/logging",schemaPath:"#/definitions/HotClient/properties/logging/anyOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err133];}else {vErrors.push(err133);}errors++;}}var _valid23 = _errs262 === errors;valid41 = valid41 || _valid23;}if(!valid41){const err134 = {instancePath:instancePath+"/hot/client/logging",schemaPath:"#/definitions/HotClient/properties/logging/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err134];}else {vErrors.push(err134);}errors++;}else {errors = _errs260;if(vErrors !== null){if(_errs260){vErrors.length = _errs260;}else {vErrors = null;}}}var valid31 = _errs259 === errors;}else {var valid31 = true;}if(valid31){if(data45.dynamicPublicPath !== undefined){const _errs268 = errors;if(typeof data45.dynamicPublicPath !== "boolean"){const err135 = {instancePath:instancePath+"/hot/client/dynamicPublicPath",schemaPath:"#/definitions/HotClient/properties/dynamicPublicPath/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err135];}else {vErrors.push(err135);}errors++;}var valid31 = _errs268 === errors;}else {var valid31 = true;}}}}}}}}}}}}else {const err136 = {instancePath:instancePath+"/hot/client",schemaPath:"#/definitions/HotClient/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err136];}else {vErrors.push(err136);}errors++;}}var valid16 = _errs197 === errors;}else {var valid16 = true;}}}}}}}}}}}}else {const err137 = {instancePath:instancePath+"/hot",schemaPath:"#/properties/hot/anyOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err137];}else {vErrors.push(err137);}errors++;}}var _valid7 = _errs128 === errors;valid15 = valid15 || _valid7;}if(!valid15){const err138 = {instancePath:instancePath+"/hot",schemaPath:"#/properties/hot/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};if(vErrors === null){vErrors = [err138];}else {vErrors.push(err138);}errors++;validate10.errors = vErrors;return false;}else {errors = _errs125;if(vErrors !== null){if(_errs125){vErrors.length = _errs125;}else {vErrors = null;}}}var valid0 = _errs124 === errors;}else {var valid0 = true;}}}}}}}}}}}}}}}}}}}}}else {validate10.errors = [{instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}validate10.errors = vErrors;return errors === 0;} \ No newline at end of file diff --git a/src/options.json b/src/options.json index 93e88603d..0bf78c07c 100644 --- a/src/options.json +++ b/src/options.json @@ -523,21 +523,14 @@ "additionalProperties": true }, "inject": { - "description": "Add the hot client entry and HotModuleReplacementPlugin to the compilation. Turn it off to wire them yourself.", - "link": "https://github.com/webpack/webpack-dev-middleware#hot", - "type": "boolean" + "description": "What is added to the compilation: `all` (the default) adds the runtime — this package's client and overlay — and HotModuleReplacementPlugin; `plugin` adds only the plugin, for a page that wires a client of its own; `client` adds only the runtime, for a configuration that applies the plugin itself; `none` adds nothing.", + "link": "https://github.com/webpack/webpack-dev-middleware#hotinject", + "enum": ["all", "plugin", "client", "none"] }, "client": { - "description": "Options handed to the browser runtime through its entry query. `false` adds no runtime to the page while still applying `HotModuleReplacementPlugin`, for a page that wires a client of its own.", + "description": "Options handed to the browser runtime through its entry query.", "link": "https://github.com/webpack/webpack-dev-middleware#hot", - "anyOf": [ - { - "enum": [false] - }, - { - "$ref": "#/definitions/HotClient" - } - ] + "$ref": "#/definitions/HotClient" } } } diff --git a/src/utils.js b/src/utils.js index 2fd168038..6ef2c6c80 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1361,7 +1361,7 @@ function isClientRequest(request, context) { * * Best effort by design: `entry` can be a function, and a request can reach the * client through an alias or a loader. Missing one of those costs a duplicate - * entry, not a broken build, and `hot.inject: false` is the way out. + * entry, not a broken build, and `hot.inject: "plugin"` is the way out. * @param {Compiler} compiler compiler * @returns {string[] | null} the names that need one, or null when they all do */ @@ -1576,20 +1576,24 @@ function resolveClientTransport(request, context) { /** * @param {Compiler[]} compilers compilers to modify - * @param {{ path: string, transport: NonNullable, inject?: boolean, client?: HotClientOptions | false, token?: string | false }} options resolved hot options + * @param {{ path: string, transport: NonNullable, inject?: HotOptions["inject"], client?: HotClientOptions, token?: string | false }} options resolved hot options * @param {Logger} logger logger */ function injectHotClient(compilers, options, logger) { - if (options.inject === false) { + // What goes into the compilation: the runtime in the page, which is this + // package's client and its overlay, and `HotModuleReplacementPlugin`, which + // is webpack's hot logic. Both by default; either one, for a page that wires + // the other itself; or nothing. + const inject = options.inject || "all"; + + if (inject === "none") { return; } - // `client: false` is no runtime in the page while the compilation still - // gets everything else — the plugin, for a page that wires a client of its - // own and still wants its updates. - const addsClient = options.client !== false; + const addsClient = inject === "all" || inject === "client"; + const addsPlugin = inject === "all" || inject === "plugin"; /** @type {HotClientOptions | undefined} */ - const clientOptions = options.client || undefined; + const clientOptions = options.client; let warned = false; // A token only reaches the browser on the entry added below, so a required @@ -1670,7 +1674,7 @@ function injectHotClient(compilers, options, logger) { if (!warned) { warned = true; logger.warn( - "'hot.transport' is a function, so no client was added: the built-in one speaks Server-Sent Events and WebSocket, not a transport of your own. Set 'hot.client.transport' if yours speaks one of them, or add an entry for the client that speaks it — 'HotModuleReplacementPlugin' is still applied for you, and 'hot.inject: false' silences this.", + `'hot.transport' is a function, so no client was added: the built-in one speaks Server-Sent Events and WebSocket, not a transport of your own. Set 'hot.client.transport' if yours speaks one of them, or add an entry for the client that speaks it${addsPlugin ? " — 'HotModuleReplacementPlugin' is still applied for you" : ""}, and 'hot.inject: "${addsPlugin ? "plugin" : "none"}"' silences this.`, ); } } else { @@ -1715,11 +1719,16 @@ function injectHotClient(compilers, options, logger) { // Applying a build to the page by reloading it, or not at all, has no use // for the HMR runtime, which would only add to the bundle. It is left out - // when `hot.client.apply` says so; a plugin written into the configuration - // is the developer's and stays. + // when `hot.client.apply` says so, and whatever the mode when `hot.inject` + // leaves the plugin to the developer; a plugin written into the + // configuration is the developer's and stays. + // The mode is the injected client's, so it only counts when one is added. const needsHmr = - !clientOptions || - (clientOptions.apply !== "reload" && clientOptions.apply !== "nothing"); + addsPlugin && + (!addsClient || + !clientOptions || + (clientOptions.apply !== "reload" && + clientOptions.apply !== "nothing")); const hmrPluginExists = compiler.options.plugins.some( (plugin) => diff --git a/test/__snapshots__/validation-options.test.js.snap.webpack5 b/test/__snapshots__/validation-options.test.js.snap.webpack5 index 63b7b06f9..f4eda7566 100644 --- a/test/__snapshots__/validation-options.test.js.snap.webpack5 +++ b/test/__snapshots__/validation-options.test.js.snap.webpack5 @@ -138,6 +138,13 @@ exports[`validation should throw an error on the "hot" option with "{"client":{" -> Options handed to the browser runtime through its entry query." `; +exports[`validation should throw an error on the "hot" option with "{"client":false}" value 1`] = ` +"Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. + - options.hot.client should be an object: + object { transport?, url?, name?, overlay?, progress?, apply?, connect?, pageParamPrefix?, logging?, dynamicPublicPath? } + -> Options handed to the browser runtime through its entry query." +`; + exports[`validation should throw an error on the "hot" option with "{"heartbeat":-1}" value 1`] = ` "Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. - options.hot.heartbeat should be >= 1. @@ -150,6 +157,22 @@ exports[`validation should throw an error on the "hot" option with "{"heartbeat" -> Heartbeat interval (in milliseconds) used to keep the connection alive." `; +exports[`validation should throw an error on the "hot" option with "{"inject":false}" value 1`] = ` +"Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. + - options.hot.inject should be one of these: + "all" | "plugin" | "client" | "none" + -> What is added to the compilation: \`all\` (the default) adds the runtime — this package's client and overlay — and HotModuleReplacementPlugin; \`plugin\` adds only the plugin, for a page that wires a client of its own; \`client\` adds only the runtime, for a configuration that applies the plugin itself; \`none\` adds nothing. + -> Read more at https://github.com/webpack/webpack-dev-middleware#hotinject" +`; + +exports[`validation should throw an error on the "hot" option with "{"inject":true}" value 1`] = ` +"Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. + - options.hot.inject should be one of these: + "all" | "plugin" | "client" | "none" + -> What is added to the compilation: \`all\` (the default) adds the runtime — this package's client and overlay — and HotModuleReplacementPlugin; \`plugin\` adds only the plugin, for a page that wires a client of its own; \`client\` adds only the runtime, for a configuration that applies the plugin itself; \`none\` adds nothing. + -> Read more at https://github.com/webpack/webpack-dev-middleware#hotinject" +`; + exports[`validation should throw an error on the "hot" option with "{"path":""}" value 1`] = ` "Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. - options.hot.path should match pattern "^/[^?#]*$". @@ -177,7 +200,7 @@ exports[`validation should throw an error on the "hot" option with "{"path":"hmr exports[`validation should throw an error on the "hot" option with "{"server":{}}" value 1`] = ` "Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. - options.hot has an unknown property 'server'. These properties are valid: - object { transport?, path?, heartbeat?, ws?, progress?, token?, cors?, statsOptions?, inject?, client? }" + object { transport?, path?: string, heartbeat?: number, ws?, progress?: boolean, token?, cors?, statsOptions?, inject?, client? }" `; exports[`validation should throw an error on the "hot" option with "{"statsOptions":"errors-only"}" value 1`] = ` @@ -197,7 +220,7 @@ exports[`validation should throw an error on the "hot" option with "{"statsOptio exports[`validation should throw an error on the "hot" option with "{"transport":"websocket"}" value 1`] = ` "Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. - options.hot should be one of these: - boolean | object { transport?, path?, heartbeat?, ws?, progress?, token?, cors?, statsOptions?, inject?, client? } + boolean | object { transport?, path?: string, heartbeat?: number, ws?, progress?: boolean, token?, cors?, statsOptions?, inject?, client? } -> Enable hot module replacement over a Server-Sent Events or WebSocket endpoint. -> Read more at https://github.com/webpack/webpack-dev-middleware#hot Details: @@ -213,7 +236,7 @@ exports[`validation should throw an error on the "hot" option with "{"transport" exports[`validation should throw an error on the "hot" option with "{"transport":true}" value 1`] = ` "Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. - options.hot should be one of these: - boolean | object { transport?, path?, heartbeat?, ws?, progress?, token?, cors?, statsOptions?, inject?, client? } + boolean | object { transport?, path?: string, heartbeat?: number, ws?, progress?: boolean, token?, cors?, statsOptions?, inject?, client? } -> Enable hot module replacement over a Server-Sent Events or WebSocket endpoint. -> Read more at https://github.com/webpack/webpack-dev-middleware#hot Details: @@ -229,31 +252,31 @@ exports[`validation should throw an error on the "hot" option with "{"transport" exports[`validation should throw an error on the "hot" option with "{"unknown":true}" value 1`] = ` "Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. - options.hot has an unknown property 'unknown'. These properties are valid: - object { transport?, path?, heartbeat?, ws?, progress?, token?, cors?, statsOptions?, inject?, client? }" + object { transport?, path?: string, heartbeat?: number, ws?, progress?: boolean, token?, cors?, statsOptions?, inject?, client? }" `; exports[`validation should throw an error on the "hot" option with "0" value 1`] = ` "Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. - options.hot should be one of these: - boolean | object { transport?, path?, heartbeat?, ws?, progress?, token?, cors?, statsOptions?, inject?, client? } + boolean | object { transport?, path?: string, heartbeat?: number, ws?, progress?: boolean, token?, cors?, statsOptions?, inject?, client? } -> Enable hot module replacement over a Server-Sent Events or WebSocket endpoint. -> Read more at https://github.com/webpack/webpack-dev-middleware#hot Details: * options.hot should be a boolean. * options.hot should be an object: - object { transport?, path?, heartbeat?, ws?, progress?, token?, cors?, statsOptions?, inject?, client? }" + object { transport?, path?: string, heartbeat?: number, ws?, progress?: boolean, token?, cors?, statsOptions?, inject?, client? }" `; exports[`validation should throw an error on the "hot" option with "foo" value 1`] = ` "Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. - options.hot should be one of these: - boolean | object { transport?, path?, heartbeat?, ws?, progress?, token?, cors?, statsOptions?, inject?, client? } + boolean | object { transport?, path?: string, heartbeat?: number, ws?, progress?: boolean, token?, cors?, statsOptions?, inject?, client? } -> Enable hot module replacement over a Server-Sent Events or WebSocket endpoint. -> Read more at https://github.com/webpack/webpack-dev-middleware#hot Details: * options.hot should be a boolean. * options.hot should be an object: - object { transport?, path?, heartbeat?, ws?, progress?, token?, cors?, statsOptions?, inject?, client? }" + object { transport?, path?: string, heartbeat?: number, ws?, progress?: boolean, token?, cors?, statsOptions?, inject?, client? }" `; exports[`validation should throw an error on the "index" option with "{}" value 1`] = ` diff --git a/test/e2e/inject.test.js b/test/e2e/inject.test.js index 6cc80e8c3..73b598a70 100644 --- a/test/e2e/inject.test.js +++ b/test/e2e/inject.test.js @@ -62,11 +62,11 @@ describe("hot with nothing but the middleware (browser)", () => { ); }); - it("leaves the compilation alone when injection is off", async () => { + it("leaves the compilation alone when inject is none", async () => { hotApp = await createHotApp({ bare: true, code: acceptedApp("v1"), - hot: { inject: false }, + hot: { inject: "none" }, }); ({ page, browser } = await runBrowser()); const console_ = collectConsole(page); @@ -83,6 +83,53 @@ describe("hot with nothing but the middleware (browser)", () => { expect(console_.messages.join("\n")).not.toContain("connected"); }); + it("adds the client and leaves the plugin to you with inject client", async () => { + hotApp = await createHotApp({ + code: acceptedApp("v1"), + // The configuration's own plugin and client entry, as a project that + // applies the plugin itself has them. + hot: { inject: "client" }, + }); + ({ page, browser } = await runBrowser()); + const console_ = collectConsole(page); + + await page.goto(hotApp.url); + await waitForAppText(page, "v1"); + await console_.waitFor("connected"); + await page.evaluate(() => { + globalThis.notReloaded = true; + }); + + hotApp.edit(acceptedApp("v2")); + await waitForAppText(page, "v2"); + + // Applied in place by the plugin the configuration has, which the + // middleware neither duplicated nor asked to be dropped. + expect(await page.evaluate(() => globalThis.notReloaded)).toBe(true); + }); + + it("adds only the client with inject client and no plugin of your own", async () => { + hotApp = await createHotApp({ + bare: true, + code: ` + document.getElementById("app").textContent = "v1"; + globalThis.hasHotRuntime = Boolean(module.hot); + `, + hot: { inject: "client" }, + }); + ({ page, browser } = await runBrowser()); + const console_ = collectConsole(page); + + await page.goto(hotApp.url); + await waitForAppText(page, "v1"); + + // The runtime is added and connects; webpack's hot logic is not in the + // bundle. + await console_.waitFor("connected"); + + expect(await page.evaluate(() => globalThis.hasHotRuntime)).toBe(false); + }); + it("hands the browser options to the runtime", async () => { hotApp = await createHotApp({ bare: true, diff --git a/test/e2e/messages.test.js b/test/e2e/messages.test.js index ecf179e4a..3ea8e00c0 100644 --- a/test/e2e/messages.test.js +++ b/test/e2e/messages.test.js @@ -322,7 +322,7 @@ describe("a module standing in for the client (browser)", () => { hotApp = await createHotApp({ bare: true, - hot: { inject: false, path: "/stand-in-hmr" }, + hot: { inject: "none", path: "/stand-in-hmr" }, files: { "stand-in.js": ` globalThis.__webpack_dev_middleware_client_query__ = "?path=/stand-in-hmr"; diff --git a/test/e2e/process-update.test.js b/test/e2e/process-update.test.js index 81d9e42e4..577ce1eef 100644 --- a/test/e2e/process-update.test.js +++ b/test/e2e/process-update.test.js @@ -304,7 +304,7 @@ describe("update processing (browser)", () => { hmrPlugin: false, // `hot` applies the plugin itself now, so the only way to reach a // compilation without a hot runtime is to turn that off. - hot: { inject: false }, + hot: { inject: "none" }, }); ({ page, browser } = await runBrowser()); const console_ = collectConsole(page); diff --git a/test/inject-client.test.js b/test/inject-client.test.js index 432ccbdb2..fa07f2995 100644 --- a/test/inject-client.test.js +++ b/test/inject-client.test.js @@ -757,13 +757,13 @@ describe("what injectHotClient leaves alone", () => { return created; } - it("adds nothing at all when inject is off", () => { + it("adds nothing at all when inject is none", () => { const instance = compiler(); const before = entryCount(instance); injectHotClient( [instance], - { path: "/__webpack_hmr", transport: "sse", inject: false }, + { path: "/__webpack_hmr", transport: "sse", inject: "none" }, logger, ); @@ -805,7 +805,7 @@ describe("what injectHotClient leaves alone", () => { expect(hasHmrPlugin(instance)).toBe(false); }); - it("adds no client but still the plugin when the client is off", () => { + it("adds no client but still the plugin when inject is plugin", () => { // A page that wires a runtime of its own still wants its updates applied, // which takes the plugin. const instance = compiler(); @@ -813,7 +813,7 @@ describe("what injectHotClient leaves alone", () => { injectHotClient( [instance], - { path: "/__webpack_hmr", transport: "sse", client: false }, + { path: "/__webpack_hmr", transport: "sse", inject: "plugin" }, logger, ); @@ -821,14 +821,87 @@ describe("what injectHotClient leaves alone", () => { expect(hasHmrPlugin(instance)).toBe(true); }); - it("does not warn about a token it never had a client to hand to, when the client is off", () => { + it("does not warn about a token it never had a client to hand to, when inject is plugin", () => { /** @type {string[]} */ const warned = []; const instance = compiler(); injectHotClient( [instance], - { path: "/__webpack_hmr", transport: "sse", client: false }, + { path: "/__webpack_hmr", transport: "sse", inject: "plugin" }, + { warn: (message) => warned.push(message), log: () => {} }, + ); + + expect(warned).toStrictEqual([]); + }); + + it("adds the plugin with inject plugin whatever the client's mode says", () => { + // `apply` is the injected client's, and none is injected. + const instance = compiler(); + + injectHotClient( + [instance], + { + path: "/__webpack_hmr", + transport: "sse", + inject: "plugin", + client: { apply: "reload" }, + }, + logger, + ); + + expect(hasHmrPlugin(instance)).toBe(true); + }); + + it("does not say the plugin is applied for a transport of your own when inject is client", () => { + /** @type {string[]} */ + const warned = []; + const instance = compiler(); + + injectHotClient( + [instance], + { + path: "/__webpack_hmr", + transport: () => ({ + close: () => {}, + onConnect: () => {}, + publish: () => {}, + publishTo: () => {}, + }), + inject: "client", + }, + { warn: (message) => warned.push(message), log: () => {} }, + ); + + expect(hasHmrPlugin(instance)).toBe(false); + expect(warned.join("\n")).toContain("no client was added"); + expect(warned.join("\n")).not.toContain("still applied"); + }); + + it("adds the client but not the plugin when inject is client", () => { + const instance = compiler(); + const before = entryCount(instance); + + injectHotClient( + [instance], + { path: "/__webpack_hmr", transport: "sse", inject: "client" }, + logger, + ); + + expect(entryCount(instance)).toBe(before + 1); + expect(hasHmrPlugin(instance)).toBe(false); + }); + + it("does not ask for a plugin of your own to be dropped when inject is client", () => { + /** @type {string[]} */ + const warned = []; + const instance = compiler({ + plugins: [new webpack.HotModuleReplacementPlugin()], + }); + + injectHotClient( + [instance], + { path: "/__webpack_hmr", transport: "sse", inject: "client" }, { warn: (message) => warned.push(message), log: () => {} }, ); diff --git a/test/universal-target.test.js b/test/universal-target.test.js index b140697e9..3be749739 100644 --- a/test/universal-target.test.js +++ b/test/universal-target.test.js @@ -114,7 +114,7 @@ const CLIENTS = [ ], [ "the client through a re-export of it", - () => ({ inject: false }), + () => ({ inject: "none" }), (dir) => [`${path.join(dir, "stand-in.js")}?path=/hmr`, "./app.js"], /stand-in\.js\?/, ], diff --git a/test/validation-options.test.js b/test/validation-options.test.js index d33e86a39..b7107dc52 100644 --- a/test/validation-options.test.js +++ b/test/validation-options.test.js @@ -107,7 +107,10 @@ describe("validation", () => { }), }, { statsOptions: { all: false } }, - { client: false }, + { inject: "all" }, + { inject: "plugin" }, + { inject: "client" }, + { inject: "none" }, { client: { url: "/__hmr" } }, { client: { url: "wss://dev.example.com/__hmr" } }, { client: { url: { port: 8080 } } }, @@ -145,6 +148,10 @@ describe("validation", () => { { client: { autoConnect: false } }, { client: { reconnect: 3 } }, { client: { timeout: 5000 } }, + // One enum for what is added, rather than two switches. + { inject: false }, + { inject: true }, + { client: false }, ], }, }; diff --git a/types/hot.d.ts b/types/hot.d.ts index 7a2b30685..cfa1adb76 100644 --- a/types/hot.d.ts +++ b/types/hot.d.ts @@ -302,13 +302,13 @@ type HotOptions = { */ token?: (boolean | string) | undefined; /** - * add the hot client entry and `HotModuleReplacementPlugin` to the compilation (default `true`); turn it off to wire them yourself + * what is added to the compilation: the runtime and `HotModuleReplacementPlugin` (`"all"`, the default), the plugin alone for a page that wires a client of its own, the runtime alone for a configuration that applies the plugin itself, or nothing */ - inject?: boolean | undefined; + inject?: ("all" | "plugin" | "client" | "none") | undefined; /** - * options handed to the browser runtime through its entry query; `false` adds no runtime to the page and still applies `HotModuleReplacementPlugin` + * options handed to the browser runtime through its entry query */ - client?: (HotClientOptions | false) | undefined; + client?: HotClientOptions | undefined; }; /** * What an origin is matched against: one origin, several, a pattern, or a diff --git a/types/utils.d.ts b/types/utils.d.ts index f3436d7a1..9bd2aa1c2 100644 --- a/types/utils.d.ts +++ b/types/utils.d.ts @@ -346,7 +346,7 @@ export function initState< */ /** * @param {Compiler[]} compilers compilers to modify - * @param {{ path: string, transport: NonNullable, inject?: boolean, client?: HotClientOptions | false, token?: string | false }} options resolved hot options + * @param {{ path: string, transport: NonNullable, inject?: HotOptions["inject"], client?: HotClientOptions, token?: string | false }} options resolved hot options * @param {Logger} logger logger */ export function injectHotClient( @@ -354,8 +354,8 @@ export function injectHotClient( options: { path: string; transport: NonNullable; - inject?: boolean; - client?: HotClientOptions | false; + inject?: HotOptions["inject"]; + client?: HotClientOptions; token?: string | false; }, logger: Logger,