Initial commit: Aeroflot Flights Web - Angular 12 baseline

- Angular 12 application with PrimeNG components
- 5 existing Cypress e2e test suites
- SCSS styling with BEM naming convention
- i18n support (10 languages)
- Leaflet map integration
- Complete component hierarchy and routing structure

This baseline will be used for Angular → React migration.
This commit is contained in:
gnezim
2026-04-05 18:47:57 +03:00
commit 0a5ab058a6
34439 changed files with 4408974 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022-present Bytedance, Inc. and its affiliates.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+251
View File
@@ -0,0 +1,251 @@
# @rspack/plugin-react-refresh
<p>
<a href="https://www.npmjs.com/package/@rspack/plugin-react-refresh?activeTab=readme"><img src="https://img.shields.io/npm/v/@rspack/plugin-react-refresh?style=flat-square&colorA=564341&colorB=EDED91" alt="npm version" /></a>
<a href="https://npmcharts.com/compare/@rspack/plugin-react-refresh?minimal=true"><img src="https://img.shields.io/npm/dm/@rspack/plugin-react-refresh.svg?style=flat-square&colorA=564341&colorB=EDED91" alt="downloads" /></a>
<a href="https://github.com/web-infra-dev/rspack/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square&colorA=564341&colorB=EDED91" alt="license" /></a>
</p>
React refresh plugin for [Rspack](https://github.com/web-infra-dev/rspack).
## Installation
First you need to install this plugin and its dependencies:
```bash
npm add @rspack/plugin-react-refresh react-refresh -D
# or
yarn add @rspack/plugin-react-refresh react-refresh -D
# or
pnpm add @rspack/plugin-react-refresh react-refresh -D
# or
bun add @rspack/plugin-react-refresh react-refresh -D
```
## Import the plugin
Import the plugin in your code:
- ES modules:
```js
// Named import (recommended)
import { ReactRefreshRspackPlugin } from "@rspack/plugin-react-refresh";
```
- CommonJS:
```js
const ReactRefreshRspackPlugin = require("@rspack/plugin-react-refresh");
```
## Usage
Enabling [React Fast Refresh](https://reactnative.dev/docs/fast-refresh) functionality primarily involves two aspects: code injection and code transformation.
- Code injection will inject some code from the [react-refresh](https://www.npmjs.com/package/react-refresh) package, as well as some custom runtime code, all of which are integrated in this plugin and can be injected through.
- Code transformation can be added through loaders, such as [jsc.transform.react.refresh](https://swc.rs/docs/configuration/compilation#jsctransformreactrefresh) for [swc-loader](https://swc.rs/docs/usage/swc-loader) or the [react-refresh/babel](https://github.com/facebook/react/tree/main/packages/react-refresh) for [babel-loader](https://github.com/babel/babel-loader).
```js
const ReactRefreshPlugin = require("@rspack/plugin-react-refresh");
const isDev = process.env.NODE_ENV === "development";
module.exports = {
experiments: {
rspackFuture: {
disableTransformByDefault: true,
},
},
// ...
mode: isDev ? "development" : "production",
module: {
rules: [
{
test: /\.jsx$/,
use: {
loader: "builtin:swc-loader",
options: {
jsc: {
parser: {
syntax: "ecmascript",
jsx: true,
},
transform: {
react: {
development: isDev,
refresh: isDev,
},
},
},
},
},
},
],
},
plugins: [isDev && new ReactRefreshPlugin()].filter(Boolean),
};
```
Compared to the previous approach, this method decouples the React Fast Refresh code injection logic from the transformation logic. The code injection logic is handled uniformly by this plugin, while the code transformation is handled by loaders. This means that this plugin can be used in conjunction with `builtin:swc-loader`, `swc-loader`, or `babel-loader`.
## Example
- For usage with `builtin:swc-loader`, you can refer to the example at [examples/react-refresh](https://github.com/rstackjs/rspack-examples/tree/main/rspack/react-refresh/rspack.config.js), When using with `swc-loader`, simply replace `builtin:swc-loader` with `swc-loader`.
- For usage with `babel-loader`, you can refer to the example at [examples/react-refresh-babel-loader](https://github.com/rstackjs/rspack-examples/tree/main/rspack/react-refresh-babel-loader/rspack.config.js)
## Options
### test
- Type: [Rspack.RuleSetCondition](https://rspack.rs/config/module-rules#condition)
- Default: `undefined`
Specifies which files should be processed by the React Refresh loader. This option is passed to the `builtin:react-refresh-loader` as the `rule.test` condition.
Works identically to Rspack's [rule.test](https://rspack.rs/config/module-rules#rulestest) option.
```js
new ReactRefreshPlugin({
test: [/\.jsx$/, /\.tsx$/],
});
```
### include
- Type: [Rspack.RuleSetCondition](https://rspack.rs/config/module-rules#condition)
- Default: `/\.([cm]js|[jt]sx?|flow)$/i`
Explicitly includes files to be processed by the React Refresh loader. This option is passed to the `builtin:react-refresh-loader` as the `rule.include` condition.
Use this to limit processing to specific directories or file patterns.
Works identically to Rspack's [rule.include](https://rspack.rs/config/module-rules#rulesinclude) option.
```js
new ReactRefreshPlugin({
include: [/\.jsx$/, /\.tsx$/],
});
```
### exclude
- Type: [Rspack.RuleSetCondition](https://rspack.rs/config/module-rules#condition)
- Default: `/node_modules/`
Exclude files from being processed by the plugin. The value is the same as the [rule.exclude](https://rspack.rs/config/module-rules#rulesexclude) option in Rspack.
```js
new ReactRefreshPlugin({
exclude: [/node_modules/, /some-other-module/],
});
```
### resourceQuery
- Type: [Rspack.RuleSetCondition](https://rspack.rs/config/module-rules#condition)
- Default: `undefined`
Can be used to exclude certain resources from being processed by the plugin by the resource query. The value is the same as the [rule.resourceQuery](https://rspack.rs/config/module-rules#rulesresourcequery) option in Rspack.
For example, to exclude all resources with the `raw` query, such as `import rawTs from './ReactComponent.ts?raw';`, use the following:
```js
new ReactRefreshPlugin({
resourceQuery: { not: /raw/ },
});
```
### forceEnable
- Type: `boolean`
- Default: `false`
Whether to force enable the plugin.
By default, the plugin will not be enabled in non-development environments. If you want to force enable the plugin, you can set this option to `true`.
```js
new ReactRefreshPlugin({
forceEnable: true,
});
```
It is useful if you want to:
- Use the plugin in production.
- Use the plugin with the `none` mode without setting `NODE_ENV`.
- Use the plugin in environments we do not support, such as `electron-prerender` (**WARNING: Proceed at your own risk**).
### library
- Type: `string`
- Default: `output.uniqueName || output.library`
Sets a namespace for the React Refresh runtime.
It is most useful when multiple instances of React Refresh is running together simultaneously.
### overlay
- Type: `boolean | OverlayOptions`
- Default: `false`
Modify the behavior of the error overlay.
Checkout [OverlayOptions](https://github.com/rstackjs/rspack-plugin-react-refresh/blob/main/src/options.ts#L4) type signature for more details.
- Enable the error overlay:
```js
new ReactRefreshPlugin({
overlay: true,
});
```
- Configure the error overlay:
```js
new ReactRefreshPlugin({
overlay: {
// ...
},
});
```
### reloadOnRuntimeErrors
- Type: `boolean`
- Default: `false`
Config the plugin whether trigger a full page reload when an unrecoverable runtime error is encountered.
Currently, only module factory undefined error is considered as unrecoverable runtime error.
```js
new ReactRefreshPlugin({
reloadOnRuntimeErrors: true,
});
```
### reactRefreshLoader
- Type: `string`
- Default: `builtin:react-refresh-loader`
Be default, the plugin uses `builtin:react-refresh-loader` loader implementation [from Rspack](https://github.com/web-infra-dev/rspack/tree/main/crates/rspack_loader_react_refresh) in order ot inject
the React Refresh utilities into each module. `reactRefreshLoader` option allows to specify the loader, that implements
custom React Refresh instrumentation if needed.
```js
new ReactRefreshPlugin({
reactRefreshLoader: 'my-advanced-react-refresh-loader',
});
```
## Credits
Thanks to the [react-refresh-webpack-plugin](https://github.com/pmmmwh/react-refresh-webpack-plugin) created by [@pmmmwh](https://github.com/pmmmwh), which inspires implement this plugin.
## License
`@rspack/plugin-react-refresh` is [MIT licensed](https://github.com/web-infra-dev/rspack/blob/main/LICENSE).
@@ -0,0 +1,101 @@
/* global __react_refresh_error_overlay__, __react_refresh_socket__, __resourceQuery */
const events = require('./utils/errorEventHandlers.js');
const formatWebpackErrors = require('./utils/formatWebpackErrors.js');
const runWithRetry = require('./utils/retry.js');
// Setup error states
let isHotReload = false;
let hasRuntimeErrors = false;
/**
* Try dismissing the compile error overlay.
* This will also reset runtime error records (if any),
* because we have new source to evaluate.
* @returns {void}
*/
function tryDismissErrorOverlay() {
__react_refresh_error_overlay__.clearCompileError();
__react_refresh_error_overlay__.clearRuntimeErrors(!hasRuntimeErrors);
hasRuntimeErrors = false;
}
/**
* A function called after a compile success signal is received from Webpack.
* @returns {void}
*/
function handleCompileSuccess() {
isHotReload = true;
if (isHotReload) {
tryDismissErrorOverlay();
}
}
/**
* A function called after a compile errored signal is received from Webpack.
* @param {string[]} errors
* @returns {void}
*/
function handleCompileErrors(errors) {
isHotReload = true;
const formattedErrors = formatWebpackErrors(errors);
// Only show the first error
__react_refresh_error_overlay__.showCompileError(formattedErrors[0]);
}
/**
* Handles compilation messages from Webpack.
* Integrates with a compile error overlay.
* @param {*} message A Webpack HMR message sent via WebSockets.
* @returns {void}
*/
function compileMessageHandler(message) {
switch (message.type) {
case 'ok':
case 'still-ok':
case 'warnings': {
// TODO: Implement handling for warnings
handleCompileSuccess();
break;
}
case 'errors': {
handleCompileErrors(message.data);
break;
}
default: {
// Do nothing.
}
}
}
if (process.env.NODE_ENV !== 'production') {
if (typeof window !== 'undefined') {
function setupOverlay() {
// Only register if no other overlay have been registered
if (!window.__reactRefreshOverlayInjected && __react_refresh_socket__) {
// Registers handlers for compile errors with retry -
// This is to prevent mismatching injection order causing errors to be thrown
runWithRetry(function initSocket() {
__react_refresh_socket__.init(compileMessageHandler, __resourceQuery);
}, 3);
// Registers handlers for runtime errors
events.handleError(function handleError(error) {
hasRuntimeErrors = true;
__react_refresh_error_overlay__.handleRuntimeError(error);
});
events.handleUnhandledRejection(
function handleUnhandledPromiseRejection(error) {
hasRuntimeErrors = true;
__react_refresh_error_overlay__.handleRuntimeError(error);
},
);
// Mark overlay as injected to prevent double-injection
window.__reactRefreshOverlayInjected = true;
}
}
setupOverlay();
}
}
@@ -0,0 +1,63 @@
const ansiHTML = require('../../utils/ansi-html.js');
const entities = require('html-entities');
const theme = require('../theme.js');
const utils = require('../utils.js');
ansiHTML.setColors(theme);
/**
* @typedef {Object} CompileErrorTraceProps
* @property {string} errorMessage
*/
/**
* A formatter that turns Webpack compile error messages into highlighted HTML source traces.
* @param {Document} document
* @param {HTMLElement} root
* @param {CompileErrorTraceProps} props
* @returns {void}
*/
function CompileErrorTrace(document, root, props) {
const errorParts = props.errorMessage.split('\n');
if (errorParts.length) {
if (errorParts[0]) {
errorParts[0] = utils.formatFilename(errorParts[0]);
}
const errorMessage = errorParts.splice(1, 1)[0];
if (errorMessage) {
// Strip filename from the error message
errorParts.unshift(errorMessage.replace(/^(.*:)\s.*:(\s.*)$/, '$1$2'));
}
}
const stackContainer = document.createElement('pre');
stackContainer.innerHTML = entities.decode(
ansiHTML(
entities.encode(errorParts.join('\n'), {
level: 'html5',
mode: 'nonAscii',
}),
),
{ level: 'html5' },
);
stackContainer.style.fontFamily = [
'"Operator Mono SSm"',
'"Operator Mono"',
'"Fira Code Retina"',
'"Fira Code"',
'"FiraCode-Retina"',
'"Andale Mono"',
'"Lucida Console"',
'Menlo',
'Consolas',
'Monaco',
'monospace',
].join(', ');
stackContainer.style.margin = '0';
stackContainer.style.whiteSpace = 'pre-wrap';
root.appendChild(stackContainer);
}
module.exports = CompileErrorTrace;
@@ -0,0 +1,60 @@
const Spacer = require('./Spacer.js');
const theme = require('../theme.js');
/**
* @typedef {Object} PageHeaderProps
* @property {string} [message]
* @property {string} title
* @property {string} [topOffset]
*/
/**
* The header of the overlay.
* @param {Document} document
* @param {HTMLElement} root
* @param {PageHeaderProps} props
* @returns {void}
*/
function PageHeader(document, root, props) {
const pageHeaderContainer = document.createElement('div');
pageHeaderContainer.style.background = '#' + theme.dimgrey;
pageHeaderContainer.style.boxShadow = '0 1px 4px rgba(0, 0, 0, 0.3)';
pageHeaderContainer.style.color = '#' + theme.white;
pageHeaderContainer.style.left = '0';
pageHeaderContainer.style.right = '0';
pageHeaderContainer.style.padding = '1rem 1.5rem';
pageHeaderContainer.style.paddingLeft =
'max(1.5rem, env(safe-area-inset-left))';
pageHeaderContainer.style.paddingRight =
'max(1.5rem, env(safe-area-inset-right))';
pageHeaderContainer.style.position = 'fixed';
pageHeaderContainer.style.top = props.topOffset || '0';
const title = document.createElement('h3');
title.innerText = props.title;
title.style.color = '#' + theme.red;
title.style.fontSize = '1.125rem';
title.style.lineHeight = '1.3';
title.style.margin = '0';
pageHeaderContainer.appendChild(title);
if (props.message) {
title.style.margin = '0 0 0.5rem';
const message = document.createElement('span');
message.innerText = props.message;
message.style.color = '#' + theme.white;
message.style.wordBreak = 'break-word';
pageHeaderContainer.appendChild(message);
}
root.appendChild(pageHeaderContainer);
// This has to run after appending elements to root
// because we need to actual mounted height.
Spacer(document, root, {
space: pageHeaderContainer.offsetHeight.toString(10),
});
}
module.exports = PageHeader;
@@ -0,0 +1,93 @@
const Spacer = require('./Spacer.js');
const theme = require('../theme.js');
/**
* @typedef {Object} RuntimeErrorFooterProps
* @property {string} [initialFocus]
* @property {boolean} multiple
* @property {function(MouseEvent): void} onClickCloseButton
* @property {function(MouseEvent): void} onClickNextButton
* @property {function(MouseEvent): void} onClickPrevButton
*/
/**
* A fixed footer that handles pagination of runtime errors.
* @param {Document} document
* @param {HTMLElement} root
* @param {RuntimeErrorFooterProps} props
* @returns {void}
*/
function RuntimeErrorFooter(document, root, props) {
const footer = document.createElement('div');
footer.style.backgroundColor = '#' + theme.dimgrey;
footer.style.bottom = '0';
footer.style.boxShadow = '0 -1px 4px rgba(0, 0, 0, 0.3)';
footer.style.height = '2.5rem';
footer.style.left = '0';
footer.style.right = '0';
footer.style.lineHeight = '2.5rem';
footer.style.paddingBottom = '0';
footer.style.paddingBottom = 'env(safe-area-inset-bottom)';
footer.style.position = 'fixed';
footer.style.textAlign = 'center';
footer.style.zIndex = '2';
const BUTTON_CONFIGS = {
prev: {
id: 'prev',
label: '◀&ensp;Prev',
onClick: props.onClickPrevButton,
},
close: {
id: 'close',
label: '×&ensp;Close',
onClick: props.onClickCloseButton,
},
next: {
id: 'next',
label: 'Next&ensp;▶',
onClick: props.onClickNextButton,
},
};
let buttons = [BUTTON_CONFIGS.close];
if (props.multiple) {
buttons = [BUTTON_CONFIGS.prev, BUTTON_CONFIGS.close, BUTTON_CONFIGS.next];
}
/** @type {HTMLButtonElement | undefined} */
let initialFocusButton;
for (let i = 0; i < buttons.length; i += 1) {
const buttonConfig = buttons[i];
const button = document.createElement('button');
button.id = buttonConfig.id;
button.innerHTML = buttonConfig.label;
button.tabIndex = 1;
button.style.backgroundColor = '#' + theme.dimgrey;
button.style.border = 'none';
button.style.color = '#' + theme.white;
button.style.cursor = 'pointer';
button.style.fontSize = 'inherit';
button.style.height = '100%';
button.style.padding = '0.5rem 0.75rem';
button.style.width = (100 / buttons.length).toString(10) + '%';
button.addEventListener('click', buttonConfig.onClick);
if (buttonConfig.id === props.initialFocus) {
initialFocusButton = button;
}
footer.appendChild(button);
}
root.appendChild(footer);
Spacer(document, root, { space: '2.5rem' });
if (initialFocusButton) {
initialFocusButton.focus();
}
}
module.exports = RuntimeErrorFooter;
@@ -0,0 +1,38 @@
const Spacer = require('./Spacer.js');
const theme = require('../theme.js');
/**
* @typedef {Object} RuntimeErrorHeaderProps
* @property {number} currentErrorIndex
* @property {number} totalErrors
*/
/**
* A fixed header that shows the total runtime error count.
* @param {Document} document
* @param {HTMLElement} root
* @param {RuntimeErrorHeaderProps} props
* @returns {void}
*/
function RuntimeErrorHeader(document, root, props) {
const header = document.createElement('div');
header.innerText =
'Error ' + (props.currentErrorIndex + 1) + ' of ' + props.totalErrors;
header.style.backgroundColor = '#' + theme.red;
header.style.color = '#' + theme.white;
header.style.fontWeight = '500';
header.style.height = '2.5rem';
header.style.left = '0';
header.style.lineHeight = '2.5rem';
header.style.position = 'fixed';
header.style.textAlign = 'center';
header.style.top = '0';
header.style.width = '100vw';
header.style.zIndex = '2';
root.appendChild(header);
Spacer(document, root, { space: '2.5rem' });
}
module.exports = RuntimeErrorHeader;
@@ -0,0 +1,80 @@
const ErrorStackParser = require('error-stack-parser');
const theme = require('../theme.js');
const utils = require('../utils.js');
/**
* @typedef {Object} RuntimeErrorStackProps
* @property {Error} error
*/
/**
* A formatter that turns runtime error stacks into highlighted HTML stacks.
* @param {Document} document
* @param {HTMLElement} root
* @param {RuntimeErrorStackProps} props
* @returns {void}
*/
function RuntimeErrorStack(document, root, props) {
const stackTitle = document.createElement('h4');
stackTitle.innerText = 'Call Stack';
stackTitle.style.color = '#' + theme.white;
stackTitle.style.fontSize = '1.0625rem';
stackTitle.style.fontWeight = '500';
stackTitle.style.lineHeight = '1.3';
stackTitle.style.margin = '0 0 0.5rem';
const stackContainer = document.createElement('div');
stackContainer.style.fontSize = '0.8125rem';
stackContainer.style.lineHeight = '1.3';
stackContainer.style.whiteSpace = 'pre-wrap';
let errorStacks;
try {
errorStacks = ErrorStackParser.parse(props.error);
} catch (e) {
errorStacks = [];
stackContainer.innerHTML = 'No stack trace is available for this error!';
}
for (let i = 0; i < Math.min(errorStacks.length, 10); i += 1) {
const currentStack = errorStacks[i];
const functionName = document.createElement('code');
functionName.innerHTML =
'&emsp;' + currentStack.functionName || '(anonymous function)';
functionName.style.color = '#' + theme.yellow;
functionName.style.fontFamily = [
'"Operator Mono SSm"',
'"Operator Mono"',
'"Fira Code Retina"',
'"Fira Code"',
'"FiraCode-Retina"',
'"Andale Mono"',
'"Lucida Console"',
'Menlo',
'Consolas',
'Monaco',
'monospace',
].join(', ');
const fileName = document.createElement('div');
fileName.innerHTML =
'&emsp;&emsp;' +
utils.formatFilename(currentStack.fileName) +
':' +
currentStack.lineNumber +
':' +
currentStack.columnNumber;
fileName.style.color = '#' + theme.white;
fileName.style.fontSize = '0.6875rem';
fileName.style.marginBottom = '0.25rem';
stackContainer.appendChild(functionName);
stackContainer.appendChild(fileName);
}
root.appendChild(stackTitle);
root.appendChild(stackContainer);
}
module.exports = RuntimeErrorStack;
@@ -0,0 +1,19 @@
/**
* @typedef {Object} SpacerProps
* @property {string} space
*/
/**
* An empty element to add spacing manually.
* @param {Document} document
* @param {HTMLElement} root
* @param {SpacerProps} props
* @returns {void}
*/
function Spacer(document, root, props) {
const spacer = document.createElement('div');
spacer.style.paddingBottom = props.space;
root.appendChild(spacer);
}
module.exports = Spacer;
@@ -0,0 +1,25 @@
const CompileErrorTrace = require('../components/CompileErrorTrace.js');
const PageHeader = require('../components/PageHeader.js');
const Spacer = require('../components/Spacer.js');
/**
* @typedef {Object} CompileErrorContainerProps
* @property {string} errorMessage
*/
/**
* A container to render Webpack compilation error messages with source trace.
* @param {Document} document
* @param {HTMLElement} root
* @param {CompileErrorContainerProps} props
* @returns {void}
*/
function CompileErrorContainer(document, root, props) {
PageHeader(document, root, {
title: 'Failed to compile.',
});
CompileErrorTrace(document, root, { errorMessage: props.errorMessage });
Spacer(document, root, { space: '1rem' });
}
module.exports = CompileErrorContainer;
@@ -0,0 +1,29 @@
const PageHeader = require('../components/PageHeader.js');
const RuntimeErrorStack = require('../components/RuntimeErrorStack.js');
const Spacer = require('../components/Spacer.js');
/**
* @typedef {Object} RuntimeErrorContainerProps
* @property {Error} currentError
*/
/**
* A container to render runtime error messages with stack trace.
* @param {Document} document
* @param {HTMLElement} root
* @param {RuntimeErrorContainerProps} props
* @returns {void}
*/
function RuntimeErrorContainer(document, root, props) {
PageHeader(document, root, {
message: props.currentError.message,
title: props.currentError.name,
topOffset: '2.5rem',
});
RuntimeErrorStack(document, root, {
error: props.currentError,
});
Spacer(document, root, { space: '1rem' });
}
module.exports = RuntimeErrorContainer;
@@ -0,0 +1,351 @@
const RuntimeErrorFooter = require('./components/RuntimeErrorFooter.js');
const RuntimeErrorHeader = require('./components/RuntimeErrorHeader.js');
const CompileErrorContainer = require('./containers/CompileErrorContainer.js');
const RuntimeErrorContainer = require('./containers/RuntimeErrorContainer.js');
const theme = require('./theme.js');
const utils = require('./utils.js');
/**
* @callback RenderFn
* @returns {void}
*/
/* ===== Cached elements for DOM manipulations ===== */
/**
* The iframe that contains the overlay.
* @type {HTMLIFrameElement}
*/
let iframeRoot = null;
/**
* The document object from the iframe root, used to create and render elements.
* @type {Document}
*/
let rootDocument = null;
/**
* The root div elements will attach to.
* @type {HTMLDivElement}
*/
let root = null;
/**
* A Cached function to allow deferred render.
* @type {RenderFn | null}
*/
let scheduledRenderFn = null;
/* ===== Overlay State ===== */
/**
* The latest error message from Webpack compilation.
* @type {string}
*/
let currentCompileErrorMessage = '';
/**
* Index of the error currently shown by the overlay.
* @type {number}
*/
let currentRuntimeErrorIndex = 0;
/**
* The latest runtime error objects.
* @type {Error[]}
*/
let currentRuntimeErrors = [];
/**
* The render mode the overlay is currently in.
* @type {'compileError' | 'runtimeError' | null}
*/
let currentMode = null;
/**
* @typedef {Object} IframeProps
* @property {function(): void} onIframeLoad
*/
/**
* Creates the main `iframe` the overlay will attach to.
* Accepts a callback to be ran after iframe is initialized.
* @param {Document} document
* @param {HTMLElement} root
* @param {IframeProps} props
* @returns {HTMLIFrameElement}
*/
function IframeRoot(document, root, props) {
const iframe = document.createElement('iframe');
iframe.id = 'react-refresh-overlay';
iframe.src = 'about:blank';
iframe.style.border = 'none';
iframe.style.height = '100%';
iframe.style.left = '0';
iframe.style.minHeight = '100vh';
iframe.style.minHeight = '-webkit-fill-available';
iframe.style.position = 'fixed';
iframe.style.top = '0';
iframe.style.width = '100vw';
iframe.style.zIndex = '2147483647';
iframe.addEventListener('load', function onLoad() {
// Reset margin of iframe body
iframe.contentDocument.body.style.margin = '0';
props.onIframeLoad();
});
// We skip mounting and returns as we need to ensure
// the load event is fired after we setup the global variable
return iframe;
}
/**
* Creates the main `div` element for the overlay to render.
* @param {Document} document
* @param {HTMLElement} root
* @returns {HTMLDivElement}
*/
function OverlayRoot(document, root) {
const div = document.createElement('div');
div.id = 'react-refresh-overlay-error';
// Style the contents container
div.style.backgroundColor = '#' + theme.grey;
div.style.boxSizing = 'border-box';
div.style.color = '#' + theme.white;
div.style.fontFamily = [
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'"Helvetica Neue"',
'Helvetica',
'Arial',
'sans-serif',
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'Segoe UI Symbol',
].join(', ');
div.style.fontSize = '0.875rem';
div.style.height = '100%';
div.style.lineHeight = '1.3';
div.style.overflow = 'auto';
div.style.padding = '1rem 1.5rem 0';
div.style.paddingTop = 'max(1rem, env(safe-area-inset-top))';
div.style.paddingRight = 'max(1.5rem, env(safe-area-inset-right))';
div.style.paddingBottom = 'env(safe-area-inset-bottom)';
div.style.paddingLeft = 'max(1.5rem, env(safe-area-inset-left))';
div.style.width = '100vw';
root.appendChild(div);
return div;
}
/**
* Ensures the iframe root and the overlay root are both initialized before render.
* If check fails, render will be deferred until both roots are initialized.
* @param {RenderFn} renderFn A function that triggers a DOM render.
* @returns {void}
*/
function ensureRootExists(renderFn) {
if (root) {
// Overlay root is ready, we can render right away.
renderFn();
return;
}
// Creating an iframe may be asynchronous so we'll defer render.
// In case of multiple calls, function from the last call will be used.
scheduledRenderFn = renderFn;
if (iframeRoot) {
// Iframe is already ready, it will fire the load event.
return;
}
// Create the iframe root, and, the overlay root inside it when it is ready.
iframeRoot = IframeRoot(document, document.body, {
onIframeLoad: function onIframeLoad() {
rootDocument = iframeRoot.contentDocument;
root = OverlayRoot(rootDocument, rootDocument.body);
scheduledRenderFn();
},
});
// We have to mount here to ensure `iframeRoot` is set when `onIframeLoad` fires.
// This is because onIframeLoad() will be called synchronously
// or asynchronously depending on the browser.
document.body.appendChild(iframeRoot);
}
/**
* Creates the main `div` element for the overlay to render.
* @returns {void}
*/
function render() {
ensureRootExists(function () {
const currentFocus = rootDocument.activeElement;
let currentFocusId;
if (currentFocus.localName === 'button' && currentFocus.id) {
currentFocusId = currentFocus.id;
}
utils.removeAllChildren(root);
if (currentCompileErrorMessage) {
currentMode = 'compileError';
CompileErrorContainer(rootDocument, root, {
errorMessage: currentCompileErrorMessage,
});
} else if (currentRuntimeErrors.length) {
currentMode = 'runtimeError';
RuntimeErrorHeader(rootDocument, root, {
currentErrorIndex: currentRuntimeErrorIndex,
totalErrors: currentRuntimeErrors.length,
});
RuntimeErrorContainer(rootDocument, root, {
currentError: currentRuntimeErrors[currentRuntimeErrorIndex],
});
RuntimeErrorFooter(rootDocument, root, {
initialFocus: currentFocusId,
multiple: currentRuntimeErrors.length > 1,
onClickCloseButton: function onClose() {
clearRuntimeErrors();
},
onClickNextButton: function onNext() {
if (currentRuntimeErrorIndex === currentRuntimeErrors.length - 1) {
return;
}
currentRuntimeErrorIndex += 1;
ensureRootExists(render);
},
onClickPrevButton: function onPrev() {
if (currentRuntimeErrorIndex === 0) {
return;
}
currentRuntimeErrorIndex -= 1;
ensureRootExists(render);
},
});
}
});
}
/**
* Destroys the state of the overlay.
* @returns {void}
*/
function cleanup() {
// Clean up and reset all internal state.
try {
document.body.removeChild(iframeRoot);
} catch (e) {
// In case user render react app directly to body will trigger `NotFoundError` when recovery from an Error
// https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild#exceptions
}
scheduledRenderFn = null;
root = null;
iframeRoot = null;
}
/**
* Clears Webpack compilation errors and dismisses the compile error overlay.
* @returns {void}
*/
function clearCompileError() {
if (!root || currentMode !== 'compileError') {
return;
}
currentCompileErrorMessage = '';
currentMode = null;
cleanup();
}
/**
* Clears runtime error records and dismisses the runtime error overlay.
* @param {boolean} [dismissOverlay] Whether to dismiss the overlay or not.
* @returns {void}
*/
function clearRuntimeErrors(dismissOverlay) {
if (!root || currentMode !== 'runtimeError') {
return;
}
currentRuntimeErrorIndex = 0;
currentRuntimeErrors = [];
if (typeof dismissOverlay === 'undefined' || dismissOverlay) {
currentMode = null;
cleanup();
}
}
/**
* Shows the compile error overlay with the specific Webpack error message.
* @param {string} message
* @returns {void}
*/
function showCompileError(message) {
if (!message) {
return;
}
currentCompileErrorMessage = message;
render();
}
/**
* Shows the runtime error overlay with the specific error records.
* @param {Error[]} errors
* @returns {void}
*/
function showRuntimeErrors(errors) {
if (!errors || !errors.length) {
return;
}
currentRuntimeErrors = errors;
render();
}
/**
* The debounced version of `showRuntimeErrors` to prevent frequent renders
* due to rapid firing listeners.
* @param {Error[]} errors
* @returns {void}
*/
const debouncedShowRuntimeErrors = utils.debounce(showRuntimeErrors, 30);
/**
* Detects if an error is a Webpack compilation error.
* @param {Error} error The error of interest.
* @returns {boolean} If the error is a Webpack compilation error.
*/
function isWebpackCompileError(error) {
return (
/Module [A-z ]+\(from/.test(error.message) ||
/Cannot find module/.test(error.message)
);
}
/**
* Handles runtime error contexts captured with EventListeners.
* Integrates with a runtime error overlay.
* @param {Error} error A valid error object.
* @returns {void}
*/
function handleRuntimeError(error) {
if (
error &&
!isWebpackCompileError(error) &&
currentRuntimeErrors.indexOf(error) === -1
) {
currentRuntimeErrors = currentRuntimeErrors.concat(error);
}
debouncedShowRuntimeErrors(currentRuntimeErrors);
}
module.exports = Object.freeze({
clearCompileError: clearCompileError,
clearRuntimeErrors: clearRuntimeErrors,
handleRuntimeError: handleRuntimeError,
showCompileError: showCompileError,
showRuntimeErrors: showRuntimeErrors,
});
@@ -0,0 +1,39 @@
/**
* @typedef {Object} Theme
* @property {string[]} reset
* @property {string} black
* @property {string} red
* @property {string} green
* @property {string} yellow
* @property {string} blue
* @property {string} magenta
* @property {string} cyan
* @property {string} white
* @property {string} lightgrey
* @property {string} darkgrey
* @property {string} grey
* @property {string} dimgrey
*/
/**
* @type {Theme} theme
* A collection of colors to be used by the overlay.
* Partially adopted from Tomorrow Night Bright.
*/
const theme = {
reset: ['transparent', 'transparent'],
black: '000000',
red: 'D34F56',
green: 'B9C954',
yellow: 'E6C452',
blue: '7CA7D8',
magenta: 'C299D6',
cyan: '73BFB1',
white: 'FFFFFF',
lightgrey: 'C7C7C7',
darkgrey: 'A9A9A9',
grey: '474747',
dimgrey: '343434',
};
module.exports = theme;
@@ -0,0 +1,74 @@
/**
* Debounce a function to delay invoking until wait (ms) have elapsed since the last invocation.
* @param {function(...*): *} fn The function to be debounced.
* @param {number} wait Milliseconds to wait before invoking again.
* @return {function(...*): void} The debounced function.
*/
function debounce(fn, wait) {
/**
* A cached setTimeout handler.
* @type {number | undefined}
*/
let timer;
/**
* @returns {void}
*/
function debounced() {
const context = this;
const args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
return fn.apply(context, args);
}, wait);
}
return debounced;
}
/**
* Prettify a filename from error stacks into the desired format.
* @param {string} filename The filename to be formatted.
* @returns {string} The formatted filename.
*/
function formatFilename(filename) {
// Strip away protocol and domain for compiled files
const htmlMatch = /^https?:\/\/(.*)\/(.*)/.exec(filename);
if (htmlMatch && htmlMatch[1] && htmlMatch[2]) {
return htmlMatch[2];
}
// Strip everything before the first directory for source files
const sourceMatch = /\/.*?([^./]+[/|\\].*)$/.exec(filename);
if (sourceMatch && sourceMatch[1]) {
return sourceMatch[1].replace(/\?$/, '');
}
// Unknown filename type, use it as is
return filename;
}
/**
* Remove all children of an element.
* @param {HTMLElement} element A valid HTML element.
* @param {number} [skip] Number of elements to skip removing.
* @returns {void}
*/
function removeAllChildren(element, skip) {
/** @type {Node[]} */
const childList = Array.prototype.slice.call(
element.childNodes,
typeof skip !== 'undefined' ? skip : 0,
);
for (let i = 0; i < childList.length; i += 1) {
element.removeChild(childList[i]);
}
}
module.exports = {
debounce: debounce,
formatFilename: formatFilename,
removeAllChildren: removeAllChildren,
};
@@ -0,0 +1,35 @@
const RefreshUtils = require('./refreshUtils');
const RefreshRuntime = require('react-refresh/runtime');
function refresh(moduleId, webpackHot) {
const currentExports = RefreshUtils.getModuleExports(moduleId);
const fn = (exports) => {
var errorOverlay;
if (typeof __react_refresh_error_overlay__ !== 'undefined') {
errorOverlay = __react_refresh_error_overlay__;
}
var testMode;
if (typeof __react_refresh_test__ !== 'undefined') {
testMode = __react_refresh_test__;
}
RefreshUtils.executeRuntime(
exports,
moduleId,
webpackHot,
errorOverlay,
testMode,
);
};
if (typeof Promise !== 'undefined' && currentExports instanceof Promise) {
currentExports.then(fn);
} else {
fn(currentExports);
}
}
module.exports = {
refresh,
register: RefreshRuntime.register,
createSignatureFunctionForTransform:
RefreshRuntime.createSignatureFunctionForTransform,
};
@@ -0,0 +1,50 @@
var RefreshRuntime = require('react-refresh/runtime');
var safeThis = (function () {
// copied from core-js-pure/features/global-this
'use strict';
var check = function (it) {
return it && it.Math == Math && it;
};
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
// eslint-disable-next-line es/no-global-this -- safe
return (
check(typeof globalThis == 'object' && globalThis) ||
check(typeof window == 'object' && window) ||
// eslint-disable-next-line no-restricted-globals -- safe
check(typeof self == 'object' && self) ||
check(typeof __webpack_require__.g == 'object' && __webpack_require__.g) ||
// eslint-disable-next-line no-new-func -- fallback
(function () {
return this;
})() ||
this ||
Function('return this')()
);
})();
if (process.env.NODE_ENV !== 'production') {
if (typeof safeThis !== 'undefined') {
var $RefreshInjected$ = '__reactRefreshInjected';
// Namespace the injected flag (if necessary) for monorepo compatibility
if (
typeof __react_refresh_library__ !== 'undefined' &&
__react_refresh_library__
) {
$RefreshInjected$ += '_' + __react_refresh_library__;
}
// Only inject the runtime if it hasn't been injected
if (!safeThis[$RefreshInjected$]) {
RefreshRuntime.injectIntoGlobalHook(safeThis);
// Empty implementation to avoid "ReferenceError: variable is not defined" in module which didn't pass builtin:react-refresh-loader
safeThis.$RefreshSig$ = () => (type) => type;
safeThis.$RefreshReg$ = () => {};
// Mark the runtime as injected to prevent double-injection
safeThis[$RefreshInjected$] = true;
}
}
}
@@ -0,0 +1,301 @@
/* global __webpack_require__ */
var Refresh = require('react-refresh/runtime');
/**
* Extracts exports from a webpack module object.
* @param {string} moduleId A Webpack module ID.
* @returns {*} An exports object from the module.
*/
function getModuleExports(moduleId) {
if (typeof moduleId === 'undefined') {
// `moduleId` is unavailable, which indicates that this module is not in the cache,
// which means we won't be able to capture any exports,
// and thus they cannot be refreshed safely.
// These are likely runtime or dynamically generated modules.
return {};
}
var maybeModule = __webpack_require__.c[moduleId];
if (typeof maybeModule === 'undefined') {
// `moduleId` is available but the module in cache is unavailable,
// which indicates the module is somehow corrupted (e.g. broken Webpacak `module` globals).
// We will warn the user (as this is likely a mistake) and assume they cannot be refreshed.
console.warn(
'[React Refresh] Failed to get exports for module: ' + moduleId + '.',
);
return {};
}
var exportsOrPromise = maybeModule.exports;
if (typeof Promise !== 'undefined' && exportsOrPromise instanceof Promise) {
return exportsOrPromise.then(function (exports) {
return exports;
});
}
return exportsOrPromise;
}
/**
* Calculates the signature of a React refresh boundary.
* If this signature changes, it's unsafe to accept the boundary.
*
* This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/907d6af22ac6ebe58572be418e9253a90665ecbd/packages/metro/src/lib/polyfills/require.js#L795-L816).
* @param {*} moduleExports A Webpack module exports object.
* @returns {string[]} A React refresh boundary signature array.
*/
function getReactRefreshBoundarySignature(moduleExports) {
var signature = [];
signature.push(Refresh.getFamilyByType(moduleExports));
if (moduleExports == null || typeof moduleExports !== 'object') {
// Exit if we can't iterate over exports.
return signature;
}
for (var key in moduleExports) {
if (key === '__esModule') {
continue;
}
signature.push(key);
signature.push(Refresh.getFamilyByType(moduleExports[key]));
}
return signature;
}
/**
* Creates a helper that performs a delayed React refresh.
* @returns {function(function(): void): void} A debounced React refresh function.
*/
function createDebounceUpdate() {
/**
* A cached setTimeout handler.
* @type {number | undefined}
*/
var refreshTimeout;
/**
* Performs react refresh on a delay and clears the error overlay.
* @param {function(): void} callback
* @returns {void}
*/
function enqueueUpdate(callback) {
if (typeof refreshTimeout === 'undefined') {
refreshTimeout = setTimeout(function () {
refreshTimeout = undefined;
Refresh.performReactRefresh();
callback();
}, 30);
}
}
return enqueueUpdate;
}
/**
* Checks if all exports are likely a React component.
*
* This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/febdba2383113c88296c61e28e4ef6a7f4939fda/packages/metro/src/lib/polyfills/require.js#L748-L774).
* @param {*} moduleExports A Webpack module exports object.
* @returns {boolean} Whether the exports are React component like.
*/
function isReactRefreshBoundary(moduleExports) {
if (Refresh.isLikelyComponentType(moduleExports)) {
return true;
}
if (
moduleExports === undefined ||
moduleExports === null ||
typeof moduleExports !== 'object'
) {
// Exit if we can't iterate over exports.
return false;
}
var hasExports = false;
var areAllExportsComponents = true;
for (var key in moduleExports) {
hasExports = true;
// This is the ES Module indicator flag
if (key === '__esModule') {
continue;
}
// We can (and have to) safely execute getters here,
// as Webpack manually assigns harmony exports to getters,
// without any side-effects attached.
// Ref: https://github.com/webpack/webpack/blob/b93048643fe74de2a6931755911da1212df55897/lib/MainTemplate.js#L281
var exportValue = moduleExports[key];
if (!Refresh.isLikelyComponentType(exportValue)) {
areAllExportsComponents = false;
}
}
return hasExports && areAllExportsComponents;
}
/**
* Checks if exports are likely a React component and registers them.
*
* This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/febdba2383113c88296c61e28e4ef6a7f4939fda/packages/metro/src/lib/polyfills/require.js#L818-L835).
* @param {*} moduleExports A Webpack module exports object.
* @param {string} moduleId A Webpack module ID.
* @returns {void}
*/
function registerExportsForReactRefresh(moduleExports, moduleId) {
if (Refresh.isLikelyComponentType(moduleExports)) {
// Register module.exports if it is likely a component
Refresh.register(moduleExports, moduleId + ' %exports%');
}
if (
moduleExports === undefined ||
moduleExports === null ||
typeof moduleExports !== 'object'
) {
// Exit if we can't iterate over the exports.
return;
}
for (var key in moduleExports) {
// Skip registering the ES Module indicator
if (key === '__esModule') {
continue;
}
var exportValue = moduleExports[key];
if (Refresh.isLikelyComponentType(exportValue)) {
var typeID = moduleId + ' %exports% ' + key;
Refresh.register(exportValue, typeID);
}
}
}
/**
* Compares previous and next module objects to check for mutated boundaries.
*
* This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/907d6af22ac6ebe58572be418e9253a90665ecbd/packages/metro/src/lib/polyfills/require.js#L776-L792).
* @param {*} prevExports The current Webpack module exports object.
* @param {*} nextExports The next Webpack module exports object.
* @returns {boolean} Whether the React refresh boundary should be invalidated.
*/
function shouldInvalidateReactRefreshBoundary(prevExports, nextExports) {
var prevSignature = getReactRefreshBoundarySignature(prevExports);
var nextSignature = getReactRefreshBoundarySignature(nextExports);
if (prevSignature.length !== nextSignature.length) {
return true;
}
for (var i = 0; i < nextSignature.length; i += 1) {
if (prevSignature[i] !== nextSignature[i]) {
return true;
}
}
return false;
}
var enqueueUpdate = createDebounceUpdate();
function executeRuntime(
moduleExports,
moduleId,
webpackHot,
refreshOverlay,
isTest,
) {
registerExportsForReactRefresh(moduleExports, moduleId);
if (webpackHot) {
var isHotUpdate = !!webpackHot.data;
var prevExports;
if (isHotUpdate) {
prevExports = webpackHot.data.prevExports;
}
if (isReactRefreshBoundary(moduleExports)) {
webpackHot.dispose(
/**
* A callback to performs a full refresh if React has unrecoverable errors,
* and also caches the to-be-disposed module.
* @param {*} data A hot module data object from Webpack HMR.
* @returns {void}
*/
function hotDisposeCallback(data) {
// We have to mutate the data object to get data registered and cached
data.prevExports = moduleExports;
},
);
webpackHot.accept(
/**
* An error handler to allow self-recovering behaviours.
* @param {Error} error An error occurred during evaluation of a module.
* @returns {void}
*/
function hotErrorHandler(error) {
console.error(error);
if (
__reload_on_runtime_errors__ &&
isUnrecoverableRuntimeError(error)
) {
location.reload();
return;
}
if (typeof refreshOverlay !== 'undefined' && refreshOverlay) {
refreshOverlay.handleRuntimeError(error);
}
if (typeof isTest !== 'undefined' && isTest) {
if (window.onHotAcceptError) {
window.onHotAcceptError(error.message);
}
}
__webpack_require__.c[moduleId].hot.accept(hotErrorHandler);
},
);
if (isHotUpdate) {
if (
isReactRefreshBoundary(prevExports) &&
shouldInvalidateReactRefreshBoundary(prevExports, moduleExports)
) {
webpackHot.invalidate();
} else {
enqueueUpdate(
/**
* A function to dismiss the error overlay after performing React refresh.
* @returns {void}
*/
function updateCallback() {
if (typeof refreshOverlay !== 'undefined' && refreshOverlay) {
refreshOverlay.clearRuntimeErrors();
}
},
);
}
}
} else {
if (isHotUpdate && typeof prevExports !== 'undefined') {
webpackHot.invalidate();
}
}
}
}
function isUnrecoverableRuntimeError(error) {
return error.message.startsWith('RuntimeError: factory is undefined');
}
module.exports = Object.freeze({
enqueueUpdate: enqueueUpdate,
executeRuntime: executeRuntime,
getModuleExports: getModuleExports,
isReactRefreshBoundary: isReactRefreshBoundary,
shouldInvalidateReactRefreshBoundary: shouldInvalidateReactRefreshBoundary,
registerExportsForReactRefresh: registerExportsForReactRefresh,
});
@@ -0,0 +1,300 @@
/* eslint-disable */
// @ts-nocheck
/**
* The following code is modified based on mahdyar/ansi-html-community
* Added support for 24-bit RGB colors.
*/
'use strict';
module.exports = ansiHTML;
// Reference to https://github.com/sindresorhus/ansi-regex
var _regANSI =
/(?:(?:\u001b\[)|\u009b)(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])|\u001b[A-M]/;
var _defColors = {
reset: ['fff', '000'], // [FOREGROUND_COLOR, BACKGROUND_COLOR]
black: '000',
red: 'ff0000',
green: '209805',
yellow: 'e8bf03',
blue: '0000ff',
magenta: 'ff00ff',
cyan: '00ffee',
lightgrey: 'f0f0f0',
darkgrey: '888',
};
var _styles = {
30: 'black',
31: 'red',
32: 'green',
33: 'yellow',
34: 'blue',
35: 'magenta',
36: 'cyan',
37: 'lightgrey',
};
var _colorMode = {
2: 'rgb',
};
var _openTags = {
1: 'font-weight:bold', // bold
2: 'opacity:0.5', // dim
3: '<i>', // italic
4: '<u>', // underscore
8: 'display:none', // hidden
9: '<del>', // delete
38: function (match) {
// color
var mode = _colorMode[match[0]];
if (mode === 'rgb') {
var r, g, b;
r = match[1];
g = match[2];
b = match[3];
match.advance(4);
return 'color: rgb(' + r + ',' + g + ',' + b + ')';
}
},
48: function (match) {
// background color
var mode = _colorMode[match[0]];
if (mode === 'rgb') {
var r, g, b;
r = match[1];
g = match[2];
b = match[3];
match.advance(4);
return 'background-color: rgb(' + r + ',' + g + ',' + b + ')';
}
},
};
var _openTagToCloseTag = {
3: '23',
4: '24',
9: '29',
};
var _closeTags = {
0: function (ansiCodes) {
if (!ansiCodes) return '</span>';
if (!ansiCodes.length) return '';
var code,
ret = '';
while ((code = ansiCodes.pop())) {
var closeTag = _openTagToCloseTag[code];
if (closeTag) {
ret += _closeTags[closeTag];
continue;
}
ret += '</span>';
}
return ret;
},
23: '</i>', // reset italic
24: '</u>', // reset underscore
29: '</del>', // reset delete
};
[21, 22, 27, 28, 39, 49].forEach(function (n) {
_closeTags[n] = '</span>';
});
/**
* Normalize ';<seq>' | '<seq>' -> '<seq>'
* @param {string | null} seq
* @returns {null | string}
*/
function normalizeSeq(seq) {
if (seq === null || seq === undefined) return null;
if (seq.startsWith(';')) {
return seq.slice(1);
}
return seq;
}
/**
* Converts text with ANSI color codes to HTML markup.
* @param {String} text
* @returns {*}
*/
function ansiHTML(text) {
// Returns the text if the string has no ANSI escape code.
if (!_regANSI.test(text)) {
return text;
}
// Cache opened sequence.
var ansiCodes = [];
// Replace with markup.
var ret = text.replace(
/\033\[(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?m/g,
function (m) {
var match = m.match(/(;?\d+)/g).map(normalizeSeq);
Object.defineProperty(match, 'advance', {
value: function (count) {
this.splice(0, count);
},
});
var seq,
rep = '';
while ((seq = match[0])) {
match.advance(1);
rep += applySeq(seq);
}
return rep;
function applySeq(seq) {
var other = _openTags[seq];
if (
other &&
(other = typeof other === 'function' ? other(match) : other)
) {
// If reset signal is encountered, we have to reset everything.
var ret = '';
if (seq === '0') {
ret += _closeTags[seq](ansiCodes);
}
// If current sequence has been opened, close it.
if (!!~ansiCodes.indexOf(seq)) {
// eslint-disable-line no-extra-boolean-cast
ansiCodes.pop();
return '</span>';
}
// Open tag.
ansiCodes.push(seq);
return (
ret + (other[0] === '<' ? other : '<span style="' + other + ';">')
);
}
var ct = _closeTags[seq];
if (typeof ct === 'function') {
return ct(ansiCodes);
} else if (ct) {
// Pop sequence
ansiCodes.pop();
return ct;
}
return '';
}
},
);
// Make sure tags are closed.
var l = ansiCodes.length;
l > 0 && (ret += Array(l + 1).join('</span>'));
return ret;
}
/**
* Customize colors.
* @param {Object} colors reference to _defColors
*/
ansiHTML.setColors = function (colors) {
if (typeof colors !== 'object') {
throw new Error('`colors` parameter must be an Object.');
}
var _finalColors = {};
for (var key in _defColors) {
var hex = colors.hasOwnProperty(key) ? colors[key] : null;
if (!hex) {
_finalColors[key] = _defColors[key];
continue;
}
if ('reset' === key) {
if (typeof hex === 'string') {
hex = [hex];
}
if (
!Array.isArray(hex) ||
hex.length === 0 ||
hex.some(function (h) {
return typeof h !== 'string';
})
) {
throw new Error(
'The value of `' +
key +
'` property must be an Array and each item could only be a hex string, e.g.: FF0000',
);
}
var defHexColor = _defColors[key];
if (!hex[0]) {
hex[0] = defHexColor[0];
}
if (hex.length === 1 || !hex[1]) {
hex = [hex[0]];
hex.push(defHexColor[1]);
}
hex = hex.slice(0, 2);
} else if (typeof hex !== 'string') {
throw new Error(
'The value of `' +
key +
'` property must be a hex string, e.g.: FF0000',
);
}
_finalColors[key] = hex;
}
_setTags(_finalColors);
};
/**
* Reset colors.
*/
ansiHTML.reset = function () {
_setTags(_defColors);
};
/**
* Expose tags, including open and close.
* @type {Object}
*/
ansiHTML.tags = {};
if (Object.defineProperty) {
Object.defineProperty(ansiHTML.tags, 'open', {
get: function () {
return _openTags;
},
});
Object.defineProperty(ansiHTML.tags, 'close', {
get: function () {
return _closeTags;
},
});
} else {
ansiHTML.tags.open = _openTags;
ansiHTML.tags.close = _closeTags;
}
function _setTags(colors) {
// reset all
_openTags['0'] =
'font-weight:normal;opacity:1;color:#' +
colors.reset[0] +
';background:#' +
colors.reset[1];
// inverse
_openTags['7'] =
'color:#' + colors.reset[1] + ';background:#' + colors.reset[0];
// dark grey
_openTags['90'] = 'color:#' + colors.darkgrey;
for (var code in _styles) {
var color = _styles[code];
var oriColor = colors[color] || '000';
_openTags[code] = 'color:#' + oriColor;
code = parseInt(code);
_openTags[(code + 10).toString()] = 'background:#' + oriColor;
}
}
ansiHTML.reset();
@@ -0,0 +1,102 @@
/**
* @callback EventCallback
* @param {string | Error | null} context
* @returns {void}
*/
/**
* @callback EventHandler
* @param {Event} event
* @returns {void}
*/
/**
* A function that creates an event handler for the `error` event.
* @param {EventCallback} callback A function called to handle the error context.
* @returns {EventHandler} A handler for the `error` event.
*/
function createErrorHandler(callback) {
return function errorHandler(event) {
if (!event || !event.error) {
return callback(null);
}
if (event.error instanceof Error) {
return callback(event.error);
}
// A non-error was thrown, we don't have a trace. :(
// Look in your browser's devtools for more information
return callback(new Error(event.error));
};
}
/**
* A function that creates an event handler for the `unhandledrejection` event.
* @param {EventCallback} callback A function called to handle the error context.
* @returns {EventHandler} A handler for the `unhandledrejection` event.
*/
function createRejectionHandler(callback) {
return function rejectionHandler(event) {
if (!event || !event.reason) {
return callback(new Error('Unknown'));
}
if (event.reason instanceof Error) {
return callback(event.reason);
}
// A non-error was rejected, we don't have a trace :(
// Look in your browser's devtools for more information
return callback(new Error(event.reason));
};
}
/**
* Creates a handler that registers an EventListener on window for a valid type
* and calls a callback when the event fires.
* @param {string} eventType A valid DOM event type.
* @param {function(EventCallback): EventHandler} createHandler A function that creates an event handler.
* @returns {register} A function that registers the EventListener given a callback.
*/
function createWindowEventHandler(eventType, createHandler) {
/**
* @type {EventHandler | null} A cached event handler function.
*/
let eventHandler = null;
/**
* Unregisters an EventListener if it has been registered.
* @returns {void}
*/
function unregister() {
if (eventHandler === null) {
return;
}
window.removeEventListener(eventType, eventHandler);
eventHandler = null;
}
/**
* Registers an EventListener if it hasn't been registered.
* @param {EventCallback} callback A function called after the event handler to handle its context.
* @returns {unregister | void} A function to unregister the registered EventListener if registration is performed.
*/
function register(callback) {
if (eventHandler !== null) {
return;
}
eventHandler = createHandler(callback);
window.addEventListener(eventType, eventHandler);
return unregister;
}
return register;
}
const handleError = createWindowEventHandler('error', createErrorHandler);
const handleUnhandledRejection = createWindowEventHandler(
'unhandledrejection',
createRejectionHandler,
);
module.exports = {
handleError: handleError,
handleUnhandledRejection: handleUnhandledRejection,
};
@@ -0,0 +1,106 @@
/**
* @typedef {Object} WebpackErrorObj
* @property {string} moduleIdentifier
* @property {string} moduleName
* @property {string} message
*/
const friendlySyntaxErrorLabel = 'Syntax error:';
/**
* Checks if the error message is for a syntax error.
* @param {string} message The raw Webpack error message.
* @returns {boolean} Whether the error message is for a syntax error.
*/
function isLikelyASyntaxError(message) {
return message.indexOf(friendlySyntaxErrorLabel) !== -1;
}
/**
* Cleans up Webpack error messages.
*
* This implementation is based on the one from [create-react-app](https://github.com/facebook/create-react-app/blob/edc671eeea6b7d26ac3f1eb2050e50f75cf9ad5d/packages/react-dev-utils/formatWebpackMessages.js).
* @param {string} message The raw Webpack error message.
* @returns {string} The formatted Webpack error message.
*/
function formatMessage(message) {
let lines = message.split('\n');
// Strip Webpack-added headers off errors/warnings
// https://github.com/webpack/webpack/blob/master/lib/ModuleError.js
lines = lines.filter(function (line) {
return !/Module [A-z ]+\(from/.test(line);
});
// Remove leading newline
if (lines.length > 2 && lines[1].trim() === '') {
lines.splice(1, 1);
}
// Remove duplicated newlines
lines = lines.filter(function (line, index, arr) {
return (
index === 0 || line.trim() !== '' || line.trim() !== arr[index - 1].trim()
);
});
// Clean up the file name
lines[0] = lines[0].replace(/^(.*) \d+:\d+-\d+$/, '$1');
// Cleans up verbose "module not found" messages for files and packages.
if (lines[1] && lines[1].indexOf('Module not found: ') === 0) {
lines = [
lines[0],
lines[1]
.replace('Error: ', '')
.replace('Module not found: Cannot find file:', 'Cannot find file:'),
];
}
message = lines.join('\n');
// Clean up syntax errors
message = message.replace('SyntaxError:', friendlySyntaxErrorLabel);
// Internal stacks are generally useless, so we strip them -
// except the stacks containing `webpack:`,
// because they're normally from user code generated by webpack.
message = message.replace(
/^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm,
'',
); // at ... ...:x:y
message = message.replace(
/^\s*at\s((?!webpack:).)*<anonymous>[\s)]*(\n|$)/gm,
'',
); // at ... <anonymous>
message = message.replace(/^\s*at\s<anonymous>(\n|$)/gm, ''); // at <anonymous>
return message.trim();
}
/**
* Formats Webpack error messages into a more readable format.
* @param {Array<string | WebpackErrorObj>} errors An array of Webpack error messages.
* @returns {string[]} The formatted Webpack error messages.
*/
function formatWebpackErrors(errors) {
let formattedErrors = errors.map(function (errorObjOrMessage) {
// Webpack 5 compilation errors are in the form of descriptor objects,
// so we have to join pieces to get the format we want.
if (typeof errorObjOrMessage === 'object') {
return formatMessage(
[errorObjOrMessage.moduleName, errorObjOrMessage.message].join('\n'),
);
}
// Webpack 4 compilation errors are strings
return formatMessage(errorObjOrMessage);
});
if (formattedErrors.some(isLikelyASyntaxError)) {
// If there are any syntax errors, show just them.
formattedErrors = formattedErrors.filter(isLikelyASyntaxError);
}
return formattedErrors;
}
module.exports = formatWebpackErrors;
@@ -0,0 +1,23 @@
function runWithRetry(callback, maxRetries) {
function executeWithRetryAndTimeout(currentCount) {
try {
if (currentCount > maxRetries - 1) {
console.warn('[React Refresh] Failed to set up the socket connection.');
return;
}
callback();
} catch (err) {
setTimeout(
function () {
executeWithRetryAndTimeout(currentCount + 1);
},
Math.pow(10, currentCount),
);
}
}
executeWithRetryAndTimeout(0);
}
module.exports = runWithRetry;
+14
View File
@@ -0,0 +1,14 @@
import type { Compiler } from '@rspack/core';
import type { NormalizedPluginOptions, PluginOptions } from './options';
export type { PluginOptions };
declare class ReactRefreshRspackPlugin {
options: NormalizedPluginOptions;
/**
* @deprecated
*/
static get deprecated_runtimePaths(): string[];
constructor(options?: PluginOptions);
apply(compiler: Compiler): void;
}
export { ReactRefreshRspackPlugin };
export default ReactRefreshRspackPlugin;
+255
View File
@@ -0,0 +1,255 @@
"use strict";
var __webpack_require__ = {};
(()=>{
__webpack_require__.n = (module)=>{
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
__webpack_require__.d(getter, {
a: getter
});
return getter;
};
})();
(()=>{
__webpack_require__.d = (exports1, definition)=>{
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
enumerable: true,
get: definition[key]
});
};
})();
(()=>{
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
__webpack_require__.r = (exports1)=>{
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
value: 'Module'
});
Object.defineProperty(exports1, '__esModule', {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
ReactRefreshRspackPlugin: ()=>ReactRefreshRspackPlugin,
default: ()=>src
});
const external_node_path_namespaceObject = require("node:path");
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
const d = (object, property, defaultValue)=>{
if (void 0 === object[property] && void 0 !== defaultValue) object[property] = defaultValue;
return object[property];
};
const normalizeOverlay = (options)=>{
const defaultOverlay = {
entry: external_node_path_default().join(__dirname, '../client/errorOverlayEntry.js'),
module: external_node_path_default().join(__dirname, '../client/overlay/index.js'),
sockIntegration: 'wds'
};
if (!options) return false;
if (void 0 === options || true === options) return defaultOverlay;
options.entry = options.entry ?? defaultOverlay.entry;
options.module = options.module ?? defaultOverlay.module;
options.sockIntegration = options.sockIntegration ?? defaultOverlay.sockIntegration;
return options;
};
function normalizeOptions(options) {
d(options, 'exclude', /node_modules/i);
d(options, 'include', /\.([cm]js|[jt]sx?|flow)$/i);
d(options, 'library');
d(options, 'forceEnable', false);
d(options, 'injectLoader', true);
d(options, 'injectEntry', true);
d(options, 'reloadOnRuntimeErrors', false);
d(options, 'reactRefreshLoader', 'builtin:react-refresh-loader');
options.overlay = normalizeOverlay(options.overlay);
return options;
}
const reactRefreshPath = external_node_path_default().join(__dirname, '../client/reactRefresh.js');
const reactRefreshEntryPath = external_node_path_default().join(__dirname, '../client/reactRefreshEntry.js');
const refreshUtilsPath = external_node_path_default().join(__dirname, '../client/refreshUtils.js');
let refreshRuntimeDirPath;
function getRefreshRuntimeDirPath() {
if (!refreshRuntimeDirPath) refreshRuntimeDirPath = external_node_path_default().dirname(require.resolve('react-refresh', {
paths: [
reactRefreshPath
]
}));
return refreshRuntimeDirPath;
}
const getRefreshRuntimePaths = ()=>[
reactRefreshEntryPath,
reactRefreshPath,
refreshUtilsPath,
getRefreshRuntimeDirPath()
];
const external_node_querystring_namespaceObject = require("node:querystring");
var external_node_querystring_default = /*#__PURE__*/ __webpack_require__.n(external_node_querystring_namespaceObject);
function getAdditionalEntries({ devServer, options }) {
const resourceQuery = {};
if (devServer) {
const { client, https, http2, sockHost, sockPath, sockPort } = devServer;
let { host, path, port } = devServer;
let protocol = https || http2 ? 'https' : 'http';
if (sockHost) host = sockHost;
if (sockPath) path = sockPath;
if (sockPort) port = sockPort;
if (client && null != client.webSocketURL) {
let parsedUrl = client.webSocketURL;
if ('string' == typeof parsedUrl) parsedUrl = new URL(parsedUrl);
let auth;
if (parsedUrl.username) {
auth = parsedUrl.username;
if (parsedUrl.password) auth += `:${parsedUrl.password}`;
}
if (null != parsedUrl.hostname) host = [
null != auth && auth,
parsedUrl.hostname
].filter(Boolean).join('@');
if (null != parsedUrl.pathname) path = parsedUrl.pathname;
if (null != parsedUrl.port) port = [
'0',
'auto'
].includes(String(parsedUrl.port)) ? void 0 : parsedUrl.port;
if (null != parsedUrl.protocol) protocol = 'auto' !== parsedUrl.protocol ? parsedUrl.protocol.replace(':', '') : 'ws';
}
if (host) resourceQuery.sockHost = host;
if (path) resourceQuery.sockPath = path;
if (port) resourceQuery.sockPort = port;
resourceQuery.sockProtocol = protocol;
}
if (options.overlay) {
const { sockHost, sockPath, sockPort, sockProtocol } = options.overlay;
if (sockHost) resourceQuery.sockHost = sockHost;
if (sockPath) resourceQuery.sockPath = sockPath;
if (sockPort) resourceQuery.sockPort = sockPort;
if (sockProtocol) resourceQuery.sockProtocol = sockProtocol;
}
const queryString = external_node_querystring_default().stringify(resourceQuery, void 0, void 0, {
encodeURIComponent (str) {
return str;
}
});
const prependEntries = [
reactRefreshEntryPath
];
const overlayEntries = [
false !== options.overlay && options.overlay?.entry && `${require.resolve(options.overlay.entry)}${queryString ? `?${queryString}` : ''}`
].filter(Boolean);
return {
prependEntries,
overlayEntries
};
}
function getIntegrationEntry(integrationType) {
let resolvedEntry;
switch(integrationType){
case 'whm':
resolvedEntry = 'webpack-hot-middleware/client';
break;
}
return resolvedEntry;
}
function getSocketIntegration(integrationType) {
let resolvedSocketIntegration;
switch(integrationType){
case 'wds':
resolvedSocketIntegration = external_node_path_default().join(__dirname, './sockets/WDSSocket.js');
break;
case 'whm':
resolvedSocketIntegration = external_node_path_default().join(__dirname, './sockets/WHMEventSource.js');
break;
default:
resolvedSocketIntegration = require.resolve(integrationType);
break;
}
return resolvedSocketIntegration;
}
function addEntry(entry, compiler) {
new compiler.rspack.EntryPlugin(compiler.context, entry, {
name: void 0
}).apply(compiler);
}
function addSocketEntry(sockIntegration, compiler) {
const integrationEntry = getIntegrationEntry(sockIntegration);
if (integrationEntry) addEntry(integrationEntry, compiler);
}
const PLUGIN_NAME = 'ReactRefreshRspackPlugin';
class ReactRefreshRspackPlugin {
options;
static get deprecated_runtimePaths() {
return getRefreshRuntimePaths();
}
constructor(options = {}){
this.options = normalizeOptions(options);
}
apply(compiler) {
if (('development' !== compiler.options.mode || process.env.NODE_ENV && 'production' === process.env.NODE_ENV) && !this.options.forceEnable) return;
const addEntries = getAdditionalEntries({
devServer: compiler.options.devServer,
options: this.options
});
if (this.options.injectEntry) for (const entry of addEntries.prependEntries)addEntry(entry, compiler);
if (false !== this.options.overlay && this.options.overlay.sockIntegration) addSocketEntry(this.options.overlay.sockIntegration, compiler);
for (const entry of addEntries.overlayEntries)addEntry(entry, compiler);
new compiler.rspack.ProvidePlugin({
$ReactRefreshRuntime$: reactRefreshPath
}).apply(compiler);
if (this.options.injectLoader) compiler.options.module.rules.unshift({
test: this.options.test,
include: this.options.include,
exclude: {
or: [
this.options.exclude,
[
...getRefreshRuntimePaths()
]
].filter(Boolean)
},
resourceQuery: this.options.resourceQuery,
dependency: {
not: [
'url'
]
},
use: this.options.reactRefreshLoader
});
const definedModules = {
__react_refresh_library__: JSON.stringify(compiler.rspack.Template.toIdentifier(this.options.library || compiler.options.output.uniqueName || compiler.options.output.library)),
__reload_on_runtime_errors__: this.options.reloadOnRuntimeErrors
};
const providedModules = {
__react_refresh_utils__: refreshUtilsPath
};
if (false === this.options.overlay) {
definedModules.__react_refresh_error_overlay__ = false;
definedModules.__react_refresh_socket__ = false;
} else {
if (this.options.overlay.module) providedModules.__react_refresh_error_overlay__ = require.resolve(this.options.overlay.module);
if (this.options.overlay.sockIntegration) providedModules.__react_refresh_socket__ = getSocketIntegration(this.options.overlay.sockIntegration);
}
new compiler.rspack.DefinePlugin(definedModules).apply(compiler);
new compiler.rspack.ProvidePlugin(providedModules).apply(compiler);
compiler.options.resolve.alias = {
'react-refresh': getRefreshRuntimeDirPath(),
...compiler.options.resolve.alias
};
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation)=>{
compilation.hooks.additionalTreeRuntimeRequirements.tap(PLUGIN_NAME, (_, runtimeRequirements)=>{
runtimeRequirements.add(compiler.rspack.RuntimeGlobals.moduleCache);
});
});
}
}
const src = ReactRefreshRspackPlugin;
exports.ReactRefreshRspackPlugin = __webpack_exports__.ReactRefreshRspackPlugin;
exports["default"] = __webpack_exports__["default"];
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
"ReactRefreshRspackPlugin",
"default"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
Object.defineProperty(exports, '__esModule', {
value: true
});
+93
View File
@@ -0,0 +1,93 @@
import type { RuleSetCondition } from '@rspack/core';
import type { IntegrationType } from './utils/getSocketIntegration';
interface OverlayOptions {
entry: string;
module: string;
sockIntegration: IntegrationType | false;
sockHost?: string;
sockPath?: string;
sockPort?: string;
sockProtocol?: string;
}
export type PluginOptions = {
/**
* Specifies which files should be processed by the React Refresh loader.
* This option is passed to the `builtin:react-refresh-loader` as the `rule.test` condition.
* Works identically to Rspack's `rule.test` option.
* @see https://rspack.rs/config/module-rules#rulestest
*/
test?: RuleSetCondition;
/**
* Explicitly includes files to be processed by the React Refresh loader.
* This option is passed to the `builtin:react-refresh-loader` as the `rule.include` condition.
* Use this to limit processing to specific directories or file patterns.
* Works identically to Rspack's `rule.include` option.
* @default /\.([cm]js|[jt]sx?|flow)$/i
* @see https://rspack.rs/config/module-rules#rulesinclude
*/
include?: RuleSetCondition | null;
/**
* Exclude files from being processed by the plugin.
* The value is the same as the `rule.exclude` option in Rspack.
* @default /node_modules/
* @see https://rspack.rs/config/module-rules#rulesexclude
*/
exclude?: RuleSetCondition | null;
/**
* Can be used to exclude certain resources from being processed by
* the plugin by the resource query.
* @see https://rspack.rs/config/module-rules#rulesresourcequery
*
* @example
* To exclude all resources with the `raw` query, such as
* `import rawTs from './ReactComponent.ts?raw';`, use the following:
* ```ts
* { resourceQuery: { not: /raw/ } }
* ```
*/
resourceQuery?: RuleSetCondition;
/**
* Sets a namespace for the React Refresh runtime.
* It is most useful when multiple instances of React Refresh is running
* together simultaneously.
* @default `output.uniqueName || output.library`
*/
library?: string;
/**
* Whether to force enable the plugin.
* By default, the plugin will not be enabled in non-development environments.
* If you want to force enable the plugin, you can set this option to `true`.
* @default false
*/
forceEnable?: boolean;
/**
* Modify the behavior of the error overlay.
* @default false
*/
overlay?: boolean | Partial<OverlayOptions>;
/**
* Whether to inject the builtin:react-refresh-loader
* @default true
*/
injectLoader?: boolean;
/**
* Whether to inject the client/reactRefreshEntry.js
* @default true
*/
injectEntry?: boolean;
/**
* Whether to reload the page on runtime errors. E.g: undefined module factory
* @default false
*/
reloadOnRuntimeErrors?: boolean;
/**
* Allows to specify custom react-refresh loader
* @default "builtin:react-refresh-loader"
*/
reactRefreshLoader?: string;
};
export interface NormalizedPluginOptions extends Required<PluginOptions> {
overlay: false | OverlayOptions;
}
export declare function normalizeOptions(options: PluginOptions): NormalizedPluginOptions;
export {};
+5
View File
@@ -0,0 +1,5 @@
export declare const reactRefreshPath: string;
export declare const reactRefreshEntryPath: string;
export declare const refreshUtilsPath: string;
export declare function getRefreshRuntimeDirPath(): string;
export declare const getRefreshRuntimePaths: () => string[];
@@ -0,0 +1,13 @@
import type { SocketClient } from './utils/getWDSMetadata';
declare global {
var __webpack_dev_server_client__: SocketClient | {
default: SocketClient;
};
}
/**
* Initializes a socket server for HMR for webpack-dev-server.
* @param messageHandler A handler to consume Webpack compilation messages.
* @param resourceQuery Webpack's `__resourceQuery` string.
* @returns
*/
export declare function init(messageHandler: (...args: unknown[]) => void, resourceQuery: string): void;
@@ -0,0 +1,63 @@
"use strict";
var __webpack_require__ = {};
(()=>{
__webpack_require__.n = (module)=>{
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
__webpack_require__.d(getter, {
a: getter
});
return getter;
};
})();
(()=>{
__webpack_require__.d = (exports1, definition)=>{
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
enumerable: true,
get: definition[key]
});
};
})();
(()=>{
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
__webpack_require__.r = (exports1)=>{
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
value: 'Module'
});
Object.defineProperty(exports1, '__esModule', {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
init: ()=>init
});
const getSocketUrlParts_js_namespaceObject = require("./utils/getSocketUrlParts.js");
var getSocketUrlParts_js_default = /*#__PURE__*/ __webpack_require__.n(getSocketUrlParts_js_namespaceObject);
const getUrlFromParts_js_namespaceObject = require("./utils/getUrlFromParts.js");
var getUrlFromParts_js_default = /*#__PURE__*/ __webpack_require__.n(getUrlFromParts_js_namespaceObject);
const getWDSMetadata_js_namespaceObject = require("./utils/getWDSMetadata.js");
var getWDSMetadata_js_default = /*#__PURE__*/ __webpack_require__.n(getWDSMetadata_js_namespaceObject);
function init(messageHandler, resourceQuery) {
if ('undefined' != typeof __webpack_dev_server_client__) {
let SocketClient;
SocketClient = 'default' in __webpack_dev_server_client__ ? __webpack_dev_server_client__.default : __webpack_dev_server_client__;
const wdsMeta = getWDSMetadata_js_default()(SocketClient);
const urlParts = getSocketUrlParts_js_default()(resourceQuery, wdsMeta);
const connection = new SocketClient(getUrlFromParts_js_default()(urlParts, wdsMeta));
connection.onMessage(function(data) {
const message = JSON.parse(data);
messageHandler(message);
});
}
}
exports.init = __webpack_exports__.init;
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
"init"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
Object.defineProperty(exports, '__esModule', {
value: true
});
@@ -0,0 +1,26 @@
/**
* The hard-coded singleton key for webpack-hot-middleware's client instance.
* [Ref](https://github.com/webpack-contrib/webpack-hot-middleware/blob/cb29abb9dde435a1ac8e9b19f82d7d36b1093198/client.js#L152)
*/
declare const singletonKey = "__webpack_hot_middleware_reporter__";
interface WHMClient {
cleanProblemsCache: () => void;
problems: () => boolean;
success: () => void;
useCustomOverlay: (customOverlay: {
showProblems: (type: string, data: string[]) => void;
clear: () => void;
}) => void;
}
declare global {
interface Window {
[singletonKey]: WHMClient;
}
}
/**
* Initializes a socket server for HMR for webpack-hot-middleware.
* @param {function(*): void} messageHandler A handler to consume Webpack compilation messages.
* @returns {void}
*/
export declare function init(messageHandler: (...args: unknown[]) => void): void;
export {};
@@ -0,0 +1,52 @@
"use strict";
var __webpack_require__ = {};
(()=>{
__webpack_require__.d = (exports1, definition)=>{
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
enumerable: true,
get: definition[key]
});
};
})();
(()=>{
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
__webpack_require__.r = (exports1)=>{
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
value: 'Module'
});
Object.defineProperty(exports1, '__esModule', {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
init: ()=>init
});
const singletonKey = '__webpack_hot_middleware_reporter__';
function init(messageHandler) {
const client = window[singletonKey];
client.useCustomOverlay({
showProblems (type, data) {
messageHandler({
type,
data
});
},
clear () {
messageHandler({
type: 'ok'
});
}
});
}
exports.init = __webpack_exports__.init;
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
"init"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
Object.defineProperty(exports, '__esModule', {
value: true
});
@@ -0,0 +1 @@
export default function getCurrentScriptSource(): string | null | undefined;
@@ -0,0 +1,45 @@
"use strict";
var __webpack_require__ = {};
(()=>{
__webpack_require__.d = (exports1, definition)=>{
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
enumerable: true,
get: definition[key]
});
};
})();
(()=>{
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
__webpack_require__.r = (exports1)=>{
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
value: 'Module'
});
Object.defineProperty(exports1, '__esModule', {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
default: ()=>getCurrentScriptSource
});
function getCurrentScriptSource() {
if ('currentScript' in document) {
if (null == document.currentScript) return;
return document.currentScript.getAttribute('src');
}
const scriptElementsWithSrc = Array.prototype.filter.call(document.scripts || [], (elem)=>elem.getAttribute('src'));
if (!scriptElementsWithSrc.length) return;
const currentScript = scriptElementsWithSrc[scriptElementsWithSrc.length - 1];
return currentScript.getAttribute('src');
}
exports["default"] = __webpack_exports__["default"];
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
"default"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
Object.defineProperty(exports, '__esModule', {
value: true
});
@@ -0,0 +1,9 @@
import type { WDSMetaObj } from './getWDSMetadata';
export interface SocketUrlParts {
auth?: string;
hostname: string;
protocol?: string;
pathname: string;
port?: string;
}
export default function getSocketUrlParts(resourceQuery?: string, metadata?: WDSMetaObj): SocketUrlParts;
@@ -0,0 +1,87 @@
"use strict";
var __webpack_require__ = {};
(()=>{
__webpack_require__.n = (module)=>{
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
__webpack_require__.d(getter, {
a: getter
});
return getter;
};
})();
(()=>{
__webpack_require__.d = (exports1, definition)=>{
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
enumerable: true,
get: definition[key]
});
};
})();
(()=>{
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
__webpack_require__.r = (exports1)=>{
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
value: 'Module'
});
Object.defineProperty(exports1, '__esModule', {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
default: ()=>getSocketUrlParts
});
const external_getCurrentScriptSource_js_namespaceObject = require("./getCurrentScriptSource.js");
var external_getCurrentScriptSource_js_default = /*#__PURE__*/ __webpack_require__.n(external_getCurrentScriptSource_js_namespaceObject);
function getSocketUrlParts(resourceQuery, metadata = {}) {
const urlParts = {};
if (resourceQuery) {
const parsedQuery = {};
const searchParams = new URLSearchParams(resourceQuery.slice(1));
searchParams.forEach((value, key)=>{
parsedQuery[key] = value;
});
urlParts.hostname = parsedQuery.sockHost;
urlParts.pathname = parsedQuery.sockPath;
urlParts.port = parsedQuery.sockPort;
if (parsedQuery.sockProtocol) urlParts.protocol = `${parsedQuery.sockProtocol}:`;
} else {
const scriptSource = external_getCurrentScriptSource_js_default()();
let url = {};
try {
url = new URL(scriptSource, window.location.href);
} catch (e) {}
if (url.username) {
urlParts.auth = url.username;
if (url.password) urlParts.auth += `:${url.password}`;
}
if ('null' !== url.origin) urlParts.hostname = url.hostname;
urlParts.protocol = url.protocol;
urlParts.port = url.port;
}
if (!urlParts.pathname) if (4 === metadata.version) urlParts.pathname = '/ws';
else urlParts.pathname = '/sockjs-node';
const isEmptyHostname = '0.0.0.0' === urlParts.hostname || '[::]' === urlParts.hostname || !urlParts.hostname;
if (isEmptyHostname && window.location.hostname && 0 === window.location.protocol.indexOf('http')) urlParts.hostname = window.location.hostname;
if (!urlParts.protocol || urlParts.hostname && (isEmptyHostname || 'https:' === window.location.protocol)) urlParts.protocol = window.location.protocol;
if (!urlParts.port) urlParts.port = window.location.port;
if (!urlParts.hostname || !urlParts.pathname) throw new Error("[React Refresh] Failed to get an URL for the socket connection.\nThis usually means that the current executed script doesn't have a `src` attribute set.\nYou should either specify the socket path parameters under the `devServer` key in your Rspack config, or use the `overlay` option.\nhttps://rspack.rs/guide/tech/react#fast-refresh");
return {
auth: urlParts.auth,
hostname: urlParts.hostname,
pathname: urlParts.pathname,
protocol: urlParts.protocol,
port: urlParts.port || void 0
};
}
exports["default"] = __webpack_exports__["default"];
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
"default"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
Object.defineProperty(exports, '__esModule', {
value: true
});
@@ -0,0 +1,9 @@
import type { SocketUrlParts } from './getSocketUrlParts';
import type { WDSMetaObj } from './getWDSMetadata';
/**
* Create a valid URL from parsed URL parts.
* @param urlParts The parsed URL parts.
* @param metadata The parsed WDS metadata object.
* @returns The generated URL.
*/
export default function urlFromParts(urlParts: SocketUrlParts, metadata?: WDSMetaObj): string;
@@ -0,0 +1,49 @@
"use strict";
var __webpack_require__ = {};
(()=>{
__webpack_require__.d = (exports1, definition)=>{
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
enumerable: true,
get: definition[key]
});
};
})();
(()=>{
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
__webpack_require__.r = (exports1)=>{
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
value: 'Module'
});
Object.defineProperty(exports1, '__esModule', {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
default: ()=>urlFromParts
});
function urlFromParts(urlParts, metadata = {}) {
let fullProtocol = 'http:';
if (urlParts.protocol) fullProtocol = urlParts.protocol;
if (metadata.enforceWs) fullProtocol = fullProtocol.replace(/^(?:http|.+-extension|file)/i, 'ws');
fullProtocol = `${fullProtocol}//`;
let fullHost = urlParts.hostname;
if (urlParts.auth) {
const fullAuth = `${urlParts.auth.split(':').map(encodeURIComponent).join(':')}@`;
fullHost = fullAuth + fullHost;
}
if (urlParts.port) fullHost = `${fullHost}:${urlParts.port}`;
const url = new URL(urlParts.pathname, fullProtocol + fullHost);
return url.href;
}
exports["default"] = __webpack_exports__["default"];
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
"default"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
Object.defineProperty(exports, '__esModule', {
value: true
});
@@ -0,0 +1,16 @@
export interface WDSMetaObj {
enforceWs?: boolean;
version?: number;
}
declare class WebSocketClient {
client: WebSocket;
constructor(url: string);
onOpen(f: (...args: unknown[]) => void): void;
onClose(f: (...args: unknown[]) => void): void;
onMessage(f: (...args: unknown[]) => void): void;
}
export interface SocketClient {
new (url: string): WebSocketClient;
}
export default function getWDSMetadata(SocketClient: SocketClient): WDSMetaObj;
export {};
@@ -0,0 +1,45 @@
"use strict";
var __webpack_require__ = {};
(()=>{
__webpack_require__.d = (exports1, definition)=>{
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
enumerable: true,
get: definition[key]
});
};
})();
(()=>{
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
__webpack_require__.r = (exports1)=>{
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
value: 'Module'
});
Object.defineProperty(exports1, '__esModule', {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
default: ()=>getWDSMetadata
});
function getWDSMetadata(SocketClient) {
let enforceWs = false;
if (void 0 !== SocketClient.name && null !== SocketClient.name && SocketClient.name.toLowerCase().includes('websocket')) enforceWs = true;
let version;
version = 'onMessage' in SocketClient.prototype ? 'getClientPath' in SocketClient || 'BaseClient' === Object.getPrototypeOf(SocketClient).name ? 3 : 4 : 3;
return {
enforceWs: enforceWs,
version: version
};
}
exports["default"] = __webpack_exports__["default"];
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
"default"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
Object.defineProperty(exports, '__esModule', {
value: true
});
@@ -0,0 +1,9 @@
import type { NormalizedPluginOptions } from '../options';
export interface AdditionalEntries {
prependEntries: string[];
overlayEntries: string[];
}
export declare function getAdditionalEntries({ devServer, options, }: {
devServer: any;
options: NormalizedPluginOptions;
}): AdditionalEntries;
@@ -0,0 +1,7 @@
import type { IntegrationType } from './getSocketIntegration';
/**
* Gets entry point of a supported socket integration.
* @param integrationType A valid socket integration type or a path to a module.
* @returns Path to the resolved integration entry point.
*/
export declare function getIntegrationEntry(integrationType: IntegrationType): string | undefined;
@@ -0,0 +1,2 @@
export type IntegrationType = 'wds' | 'whm' | (string & {});
export declare function getSocketIntegration(integrationType: IntegrationType): string;
@@ -0,0 +1,7 @@
// CommonJS wrapper
const { ReactRefreshRspackPlugin } = require('../dist/index.js');
// default export will be deprecated in next major version
module.exports = ReactRefreshRspackPlugin;
module.exports.ReactRefreshRspackPlugin = ReactRefreshRspackPlugin;
@@ -0,0 +1,3 @@
import { ReactRefreshRspackPlugin } from '../dist/index.js';
export = ReactRefreshRspackPlugin;
@@ -0,0 +1,5 @@
import { type PluginOptions, ReactRefreshRspackPlugin } from '../dist/index.js';
export type { PluginOptions };
export { ReactRefreshRspackPlugin };
export default ReactRefreshRspackPlugin;
+11
View File
@@ -0,0 +1,11 @@
// ES modules wrapper
import pluginModule from '../dist/index.js';
const ReactRefreshRspackPlugin =
pluginModule?.ReactRefreshRspackPlugin ??
pluginModule?.default ??
pluginModule;
// default export will be deprecated in next major version
export default ReactRefreshRspackPlugin;
export { ReactRefreshRspackPlugin };
+77
View File
@@ -0,0 +1,77 @@
{
"name": "@rspack/plugin-react-refresh",
"version": "1.6.1",
"repository": "https://github.com/rstackjs/rspack-plugin-react-refresh",
"license": "MIT",
"description": "React refresh plugin for Rspack",
"main": "exports/index.cjs",
"type": "commonjs",
"types": "exports/index.d.cts",
"exports": {
".": {
"require": "./exports/index.cjs",
"default": "./exports/index.mjs"
},
"./react-refresh": "./client/reactRefresh.js",
"./react-refresh-entry": "./client/reactRefreshEntry.js",
"./overlay": "./client/overlay/index.js",
"./package.json": "./package.json"
},
"files": [
"client",
"dist",
"exports"
],
"simple-git-hooks": {
"pre-commit": "npx nano-staged"
},
"nano-staged": {
"*.{js,jsx,ts,tsx,mjs,cjs}": [
"biome check --write --no-errors-on-unmatched"
]
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@rslib/core": "^0.18.2",
"@rspack/core": "^1.6.5",
"@rstest/core": "^0.6.8",
"@types/node": "^24.10.1",
"bumpp": "^10.3.2",
"cac": "^6.7.14",
"cross-env": "^10.1.0",
"execa": "9.6.1",
"fs-extra": "11.3.2",
"nano-staged": "^0.9.0",
"react-refresh": "^0.18.0",
"semver": "7.7.3",
"simple-git-hooks": "^2.13.1",
"ts-node": "^10.9.2",
"typescript": "5.9.3"
},
"dependencies": {
"error-stack-parser": "^2.1.4",
"html-entities": "^2.6.0"
},
"peerDependencies": {
"react-refresh": ">=0.10.0 <1.0.0",
"webpack-hot-middleware": "2.x"
},
"peerDependenciesMeta": {
"webpack-hot-middleware": {
"optional": true
}
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"scripts": {
"build": "rslib build",
"dev": "rslib build -w",
"lint": "biome check .",
"lint:write": "biome check . --write",
"test": "rstest",
"release": "node ./scripts/release.mjs",
"bump": "npx bumpp --no-push --no-tag --no-commit"
}
}