@rspack/plugin-react-refresh 1.0.0-alpha.0 → 1.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/client/errorOverlayEntry.js +108 -0
  2. package/client/overlay/components/CompileErrorTrace.js +58 -0
  3. package/client/overlay/components/PageHeader.js +58 -0
  4. package/client/overlay/components/RuntimeErrorFooter.js +93 -0
  5. package/client/overlay/components/RuntimeErrorHeader.js +37 -0
  6. package/client/overlay/components/RuntimeErrorStack.js +79 -0
  7. package/client/overlay/components/Spacer.js +19 -0
  8. package/client/overlay/containers/CompileErrorContainer.js +25 -0
  9. package/client/overlay/containers/RuntimeErrorContainer.js +29 -0
  10. package/client/overlay/index.js +348 -0
  11. package/client/overlay/theme.js +39 -0
  12. package/client/overlay/utils.js +74 -0
  13. package/client/utils/ansi-html.js +305 -0
  14. package/client/utils/errorEventHandlers.js +102 -0
  15. package/client/utils/formatWebpackErrors.js +96 -0
  16. package/client/utils/retry.js +23 -0
  17. package/dist/index.d.ts +2 -2
  18. package/dist/index.js +33 -3
  19. package/dist/options.d.ts +16 -1
  20. package/dist/options.js +19 -0
  21. package/dist/sockets/WDSSocket.d.ts +10 -0
  22. package/dist/sockets/WDSSocket.js +41 -0
  23. package/dist/sockets/utils/getCurrentScriptSource.d.ts +1 -0
  24. package/dist/sockets/utils/getCurrentScriptSource.js +26 -0
  25. package/dist/sockets/utils/getSocketUrlParts.d.ts +9 -0
  26. package/dist/sockets/utils/getSocketUrlParts.js +112 -0
  27. package/dist/sockets/utils/getUrlFromParts.d.ts +9 -0
  28. package/dist/sockets/utils/getUrlFromParts.js +32 -0
  29. package/dist/sockets/utils/getWDSMetadata.d.ts +5 -0
  30. package/dist/sockets/utils/getWDSMetadata.js +30 -0
  31. package/dist/utils/getAdditionalEntries.d.ts +9 -0
  32. package/dist/utils/getAdditionalEntries.js +93 -0
  33. package/dist/utils/getSocketIntegration.d.ts +2 -0
  34. package/dist/utils/getSocketIntegration.js +17 -0
  35. package/package.json +7 -3
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.init = void 0;
7
+ /**
8
+ * The following code is modified based on
9
+ * https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/f1c8b9a44198449093ca95f85af5df97925e1cfc/sockets/WPSSocket.js
10
+ *
11
+ * MIT Licensed
12
+ * Author Michael Mok
13
+ * Copyright (c) 2019 Michael Mok
14
+ * https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/0b960573797bf38926937994c481e4fec9ed8aa6/LICENSE
15
+ */
16
+ const getSocketUrlParts_1 = __importDefault(require("./utils/getSocketUrlParts"));
17
+ const getUrlFromParts_1 = __importDefault(require("./utils/getUrlFromParts"));
18
+ const getWDSMetadata_1 = __importDefault(require("./utils/getWDSMetadata"));
19
+ /**
20
+ * Initializes a socket server for HMR for webpack-dev-server.
21
+ * @param {function(*): void} messageHandler A handler to consume Webpack compilation messages.
22
+ * @param {string} [resourceQuery] Webpack's `__resourceQuery` string.
23
+ * @returns {void}
24
+ */
25
+ function init(messageHandler, resourceQuery) {
26
+ if (typeof __webpack_dev_server_client__ !== "undefined") {
27
+ let SocketClient = __webpack_dev_server_client__;
28
+ if (typeof __webpack_dev_server_client__.default !== "undefined") {
29
+ SocketClient = __webpack_dev_server_client__.default;
30
+ }
31
+ const wdsMeta = (0, getWDSMetadata_1.default)(SocketClient);
32
+ const urlParts = (0, getSocketUrlParts_1.default)(resourceQuery, wdsMeta);
33
+ const connection = new SocketClient((0, getUrlFromParts_1.default)(urlParts, wdsMeta));
34
+ // @ts-expect-error -- ignore
35
+ connection.onMessage(function onSocketMessage(data) {
36
+ const message = JSON.parse(data);
37
+ messageHandler(message);
38
+ });
39
+ }
40
+ }
41
+ exports.init = init;
@@ -0,0 +1 @@
1
+ export default function getCurrentScriptSource(): any;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function getCurrentScriptSource() {
4
+ // `document.currentScript` is the most accurate way to get the current running script,
5
+ // but is not supported in all browsers (most notably, IE).
6
+ if ("currentScript" in document) {
7
+ // In some cases, `document.currentScript` would be `null` even if the browser supports it:
8
+ // e.g. asynchronous chunks on Firefox.
9
+ // We should not fallback to the list-approach as it would not be safe.
10
+ if (document.currentScript == null)
11
+ return;
12
+ return document.currentScript.getAttribute("src");
13
+ }
14
+ else {
15
+ // Fallback to getting all scripts running in the document,
16
+ // and finding the last one injected.
17
+ const scriptElementsWithSrc = Array.prototype.filter.call(document.scripts || [], function (elem) {
18
+ return elem.getAttribute("src");
19
+ });
20
+ if (!scriptElementsWithSrc.length)
21
+ return;
22
+ const currentScript = scriptElementsWithSrc[scriptElementsWithSrc.length - 1];
23
+ return currentScript.getAttribute("src");
24
+ }
25
+ }
26
+ exports.default = getCurrentScriptSource;
@@ -0,0 +1,9 @@
1
+ import { WDSMetaObj } from "./getWDSMetadata";
2
+ export interface SocketUrlParts {
3
+ auth?: string;
4
+ hostname: string;
5
+ protocol?: string;
6
+ pathname: string;
7
+ port?: string;
8
+ }
9
+ export default function getSocketUrlParts(resourceQuery?: string, metadata?: WDSMetaObj): SocketUrlParts;
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const getCurrentScriptSource_1 = __importDefault(require("./getCurrentScriptSource"));
7
+ function getSocketUrlParts(resourceQuery, metadata) {
8
+ if (typeof metadata === "undefined") {
9
+ metadata = {};
10
+ }
11
+ /** @type {SocketUrlParts} */
12
+ let urlParts = {};
13
+ // If the resource query is available,
14
+ // parse it and ignore everything we received from the script host.
15
+ if (resourceQuery) {
16
+ const parsedQuery = {};
17
+ const searchParams = new URLSearchParams(resourceQuery.slice(1));
18
+ searchParams.forEach(function (value, key) {
19
+ // @ts-expect-error -- ignore
20
+ parsedQuery[key] = value;
21
+ });
22
+ urlParts.hostname = parsedQuery.sockHost;
23
+ urlParts.pathname = parsedQuery.sockPath;
24
+ urlParts.port = parsedQuery.sockPort;
25
+ // Make sure the protocol from resource query has a trailing colon
26
+ if (parsedQuery.sockProtocol) {
27
+ urlParts.protocol = parsedQuery.sockProtocol + ":";
28
+ }
29
+ }
30
+ else {
31
+ const scriptSource = (0, getCurrentScriptSource_1.default)();
32
+ let url = {};
33
+ try {
34
+ // The placeholder `baseURL` with `window.location.href`,
35
+ // is to allow parsing of path-relative or protocol-relative URLs,
36
+ // and will have no effect if `scriptSource` is a fully valid URL.
37
+ url = new URL(scriptSource, window.location.href);
38
+ }
39
+ catch (e) {
40
+ // URL parsing failed, do nothing.
41
+ // We will still proceed to see if we can recover using `resourceQuery`
42
+ }
43
+ // Parse authentication credentials in case we need them
44
+ if (url.username) {
45
+ // Since HTTP basic authentication does not allow empty username,
46
+ // we only include password if the username is not empty.
47
+ // Result: <username> or <username>:<password>
48
+ urlParts.auth = url.username;
49
+ if (url.password) {
50
+ urlParts.auth += ":" + url.password;
51
+ }
52
+ }
53
+ // `file://` URLs has `'null'` origin
54
+ if (url.origin !== "null") {
55
+ urlParts.hostname = url.hostname;
56
+ }
57
+ urlParts.protocol = url.protocol;
58
+ urlParts.port = url.port;
59
+ }
60
+ if (!urlParts.pathname) {
61
+ if (metadata.version === 4) {
62
+ // This is hard-coded in WDS v4
63
+ urlParts.pathname = "/ws";
64
+ }
65
+ else {
66
+ // This is hard-coded in WDS v3
67
+ urlParts.pathname = "/sockjs-node";
68
+ }
69
+ }
70
+ // Check for IPv4 and IPv6 host addresses that correspond to any/empty.
71
+ // This is important because `hostname` can be empty for some hosts,
72
+ // such as 'about:blank' or 'file://' URLs.
73
+ const isEmptyHostname = urlParts.hostname === "0.0.0.0" ||
74
+ urlParts.hostname === "[::]" ||
75
+ !urlParts.hostname;
76
+ // We only re-assign the hostname if it is empty,
77
+ // and if we are using HTTP/HTTPS protocols.
78
+ if (isEmptyHostname &&
79
+ window.location.hostname &&
80
+ window.location.protocol.indexOf("http") === 0) {
81
+ urlParts.hostname = window.location.hostname;
82
+ }
83
+ // We only re-assign `protocol` when `protocol` is unavailable,
84
+ // or if `hostname` is available and is empty,
85
+ // since otherwise we risk creating an invalid URL.
86
+ // We also do this when 'https' is used as it mandates the use of secure sockets.
87
+ if (!urlParts.protocol ||
88
+ (urlParts.hostname &&
89
+ (isEmptyHostname || window.location.protocol === "https:"))) {
90
+ urlParts.protocol = window.location.protocol;
91
+ }
92
+ // We only re-assign port when it is not available
93
+ if (!urlParts.port) {
94
+ urlParts.port = window.location.port;
95
+ }
96
+ if (!urlParts.hostname || !urlParts.pathname) {
97
+ throw new Error([
98
+ "[React Refresh] Failed to get an URL for the socket connection.",
99
+ "This usually means that the current executed script doesn't have a `src` attribute set.",
100
+ "You should either specify the socket path parameters under the `devServer` key in your Rspack config, or use the `overlay` option.",
101
+ "https://www.rspack.dev/guide/tech/react#fast-refresh"
102
+ ].join("\n"));
103
+ }
104
+ return {
105
+ auth: urlParts.auth,
106
+ hostname: urlParts.hostname,
107
+ pathname: urlParts.pathname,
108
+ protocol: urlParts.protocol,
109
+ port: urlParts.port || undefined
110
+ };
111
+ }
112
+ exports.default = getSocketUrlParts;
@@ -0,0 +1,9 @@
1
+ import type { SocketUrlParts } from "./getSocketUrlParts";
2
+ import type { WDSMetaObj } from "./getWDSMetadata";
3
+ /**
4
+ * Create a valid URL from parsed URL parts.
5
+ * @param {import('./getSocketUrlParts').SocketUrlParts} urlParts The parsed URL parts.
6
+ * @param {import('./getWDSMetadata').WDSMetaObj} [metadata] The parsed WDS metadata object.
7
+ * @returns {string} The generated URL.
8
+ */
9
+ export default function urlFromParts(urlParts: SocketUrlParts, metadata: WDSMetaObj): string;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * Create a valid URL from parsed URL parts.
5
+ * @param {import('./getSocketUrlParts').SocketUrlParts} urlParts The parsed URL parts.
6
+ * @param {import('./getWDSMetadata').WDSMetaObj} [metadata] The parsed WDS metadata object.
7
+ * @returns {string} The generated URL.
8
+ */
9
+ function urlFromParts(urlParts, metadata) {
10
+ if (typeof metadata === "undefined") {
11
+ metadata = {};
12
+ }
13
+ let fullProtocol = "http:";
14
+ if (urlParts.protocol) {
15
+ fullProtocol = urlParts.protocol;
16
+ }
17
+ if (metadata.enforceWs) {
18
+ fullProtocol = fullProtocol.replace(/^(?:http|.+-extension|file)/i, "ws");
19
+ }
20
+ fullProtocol = fullProtocol + "//";
21
+ let fullHost = urlParts.hostname;
22
+ if (urlParts.auth) {
23
+ const fullAuth = urlParts.auth.split(":").map(encodeURIComponent).join(":") + "@";
24
+ fullHost = fullAuth + fullHost;
25
+ }
26
+ if (urlParts.port) {
27
+ fullHost = fullHost + ":" + urlParts.port;
28
+ }
29
+ const url = new URL(urlParts.pathname, fullProtocol + fullHost);
30
+ return url.href;
31
+ }
32
+ exports.default = urlFromParts;
@@ -0,0 +1,5 @@
1
+ export interface WDSMetaObj {
2
+ enforceWs?: boolean;
3
+ version?: number;
4
+ }
5
+ export default function getWDSMetadata(SocketClient: any): WDSMetaObj;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function getWDSMetadata(SocketClient) {
4
+ let enforceWs = false;
5
+ if (typeof SocketClient.name !== "undefined" &&
6
+ SocketClient.name !== null &&
7
+ SocketClient.name.toLowerCase().includes("websocket")) {
8
+ enforceWs = true;
9
+ }
10
+ let version;
11
+ // WDS versions <=3.5.0
12
+ if (!("onMessage" in SocketClient.prototype)) {
13
+ version = 3;
14
+ }
15
+ else {
16
+ // WDS versions >=3.5.0 <4
17
+ if ("getClientPath" in SocketClient ||
18
+ Object.getPrototypeOf(SocketClient).name === "BaseClient") {
19
+ version = 3;
20
+ }
21
+ else {
22
+ version = 4;
23
+ }
24
+ }
25
+ return {
26
+ enforceWs: enforceWs,
27
+ version: version
28
+ };
29
+ }
30
+ exports.default = getWDSMetadata;
@@ -0,0 +1,9 @@
1
+ import type { NormalizedPluginOptions } from "../options";
2
+ export interface AdditionalEntries {
3
+ prependEntries: string[];
4
+ overlayEntries: string[];
5
+ }
6
+ export declare function getAdditionalEntries({ devServer, options }: {
7
+ devServer: any;
8
+ options: NormalizedPluginOptions;
9
+ }): AdditionalEntries;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getAdditionalEntries = void 0;
7
+ const node_querystring_1 = __importDefault(require("node:querystring"));
8
+ function getAdditionalEntries({ devServer, options }) {
9
+ /** @type {Record<string, string | number>} */
10
+ let resourceQuery = {};
11
+ if (devServer) {
12
+ const { client, https, http2, sockHost, sockPath, sockPort } = devServer;
13
+ let { host, path, port } = devServer;
14
+ let protocol = https || http2 ? "https" : "http";
15
+ if (sockHost)
16
+ host = sockHost;
17
+ if (sockPath)
18
+ path = sockPath;
19
+ if (sockPort)
20
+ port = sockPort;
21
+ if (client && client.webSocketURL != null) {
22
+ let parsedUrl = client.webSocketURL;
23
+ if (typeof parsedUrl === "string")
24
+ parsedUrl = new URL(parsedUrl);
25
+ let auth;
26
+ if (parsedUrl.username) {
27
+ auth = parsedUrl.username;
28
+ if (parsedUrl.password) {
29
+ auth += ":" + parsedUrl.password;
30
+ }
31
+ }
32
+ if (parsedUrl.hostname != null) {
33
+ host = [auth != null && auth, parsedUrl.hostname]
34
+ .filter(Boolean)
35
+ .join("@");
36
+ }
37
+ if (parsedUrl.pathname != null) {
38
+ path = parsedUrl.pathname;
39
+ }
40
+ if (parsedUrl.port != null) {
41
+ port = !["0", "auto"].includes(String(parsedUrl.port))
42
+ ? parsedUrl.port
43
+ : undefined;
44
+ }
45
+ if (parsedUrl.protocol != null) {
46
+ protocol =
47
+ parsedUrl.protocol !== "auto"
48
+ ? parsedUrl.protocol.replace(":", "")
49
+ : "ws";
50
+ }
51
+ }
52
+ if (host)
53
+ resourceQuery.sockHost = host;
54
+ if (path)
55
+ resourceQuery.sockPath = path;
56
+ if (port)
57
+ resourceQuery.sockPort = port;
58
+ resourceQuery.sockProtocol = protocol;
59
+ }
60
+ if (options.overlay) {
61
+ const { sockHost, sockPath, sockPort, sockProtocol } = options.overlay;
62
+ if (sockHost)
63
+ resourceQuery.sockHost = sockHost;
64
+ if (sockPath)
65
+ resourceQuery.sockPath = sockPath;
66
+ if (sockPort)
67
+ resourceQuery.sockPort = sockPort;
68
+ if (sockProtocol)
69
+ resourceQuery.sockProtocol = sockProtocol;
70
+ }
71
+ // We don't need to URI encode the resourceQuery as it will be parsed by Webpack
72
+ const queryString = node_querystring_1.default.stringify(resourceQuery, undefined, undefined, {
73
+ /**
74
+ * @param {string} string
75
+ * @returns {string}
76
+ */
77
+ encodeURIComponent(string) {
78
+ return string;
79
+ }
80
+ });
81
+ const prependEntries = [
82
+ // React-refresh runtime
83
+ require.resolve("../../client/reactRefreshEntry")
84
+ ];
85
+ const overlayEntries = [
86
+ // Error overlay runtime
87
+ options.overlay &&
88
+ options.overlay.entry &&
89
+ `${require.resolve(options.overlay.entry)}${queryString ? `?${queryString}` : ""}`
90
+ ].filter(Boolean);
91
+ return { prependEntries, overlayEntries };
92
+ }
93
+ exports.getAdditionalEntries = getAdditionalEntries;
@@ -0,0 +1,2 @@
1
+ export type IntegrationType = "wds";
2
+ export default function getSocketIntegration(integrationType: IntegrationType): string;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function getSocketIntegration(integrationType) {
4
+ let resolvedSocketIntegration;
5
+ switch (integrationType) {
6
+ case "wds": {
7
+ resolvedSocketIntegration = require.resolve("../sockets/WDSSocket");
8
+ break;
9
+ }
10
+ default: {
11
+ resolvedSocketIntegration = require.resolve(integrationType);
12
+ break;
13
+ }
14
+ }
15
+ return resolvedSocketIntegration;
16
+ }
17
+ exports.default = getSocketIntegration;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rspack/plugin-react-refresh",
3
- "version": "1.0.0-alpha.0",
3
+ "version": "1.0.0-alpha.1",
4
4
  "license": "MIT",
5
5
  "description": "React refresh plugin for rspack",
6
6
  "main": "dist/index.js",
@@ -30,8 +30,12 @@
30
30
  },
31
31
  "devDependencies": {
32
32
  "react-refresh": "0.14.0",
33
- "@rspack/core": "1.0.0-alpha.0",
34
- "@rspack/plugin-react-refresh": "1.0.0-alpha.0"
33
+ "@rspack/core": "1.0.0-alpha.1",
34
+ "@rspack/plugin-react-refresh": "1.0.0-alpha.1"
35
+ },
36
+ "dependencies": {
37
+ "html-entities": "^2.1.0",
38
+ "error-stack-parser": "^2.0.6"
35
39
  },
36
40
  "peerDependencies": {
37
41
  "react-refresh": ">=0.10.0 <1.0.0"