From 1d1bd34d73c4acbeb33f4f807fd0491004beb13b Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Tue, 6 Jan 2026 23:37:19 -0800 Subject: [PATCH 01/85] examples/federation: migrate to Rspack-only, Node-friendly federation - Delete webpack.config.js in component-app, lib-app and main-app - Remove legacy webpack scripts; keep Rspack build/start - Set remotes to commonjs and target async-node for tests - Set library.type=commonjs-module on remote apps - Hardcode publicPath: lib-app(3000), component-app(3001), rstest('/.rstest-temp/') - Use workspace:* for @rstest/core in main-app - Add examples/federation root test script and monorepo test:feederation - Remove nested pnpm-workspace.yaml under examples/federation - Verified Rspack builds and Playwright e2e under federation root --- .gitignore | 1 + examples/federation/.gitignore | 8 + examples/federation/README.md | 35 + examples/federation/README_zh-cn.md | 32 + examples/federation/component-app/App.jsx | 38 + .../federation/component-app/bootstrap.js | 4 + examples/federation/component-app/index.js | 1 + .../federation/component-app/package.json | 27 + .../component-app/public/index.html | 12 + .../federation/component-app/rspack.config.js | 68 + .../component-app/rspack.node.config.js | 71 + .../federation/component-app/src/Button.jsx | 36 + .../federation/component-app/src/Dialog.jsx | 43 + .../federation/component-app/src/Logo.jsx | 5 + examples/federation/component-app/src/MF.jpeg | Bin 0 -> 295619 bytes .../federation/component-app/src/ToolTip.jsx | 15 + .../federation/component-app/src/tool-tip.css | 40 + .../federation/e2e/checkApplication.spec.ts | 72 + examples/federation/main-app/App.jsx | 46 + examples/federation/main-app/bootstrap.js | 4 + .../main-app/federated-imports.test.ts | 10 + examples/federation/main-app/index.js | 1 + examples/federation/main-app/package.json | 30 + .../federation/main-app/public/index.html | 12 + examples/federation/main-app/rspack.config.js | 53 + examples/federation/main-app/rstest.config.ts | 97 + .../main-app/scripts/rstest.setup.ts | 211 ++ .../main-app/scripts/rstestGlobalSetup.ts | 12 + examples/federation/main-app/sum.test.ts | 6 + examples/federation/package.json | 23 + examples/federation/playwright.config.ts | 46 + examples/federation/runtimePlugin.js | 269 ++ package.json | 3 +- packages/core/src/config.ts | 8 + .../core/src/core/plugins/mockRuntimeCode.js | 67 + packages/core/src/core/rsbuild.ts | 6 +- .../core/src/runtime/worker/loadEsModule.ts | 14 +- .../core/src/runtime/worker/loadModule.ts | 41 +- packages/core/src/types/config.ts | 11 + pnpm-lock.yaml | 2239 ++++++++++++++++- 40 files changed, 3642 insertions(+), 75 deletions(-) create mode 100644 examples/federation/.gitignore create mode 100644 examples/federation/README.md create mode 100644 examples/federation/README_zh-cn.md create mode 100644 examples/federation/component-app/App.jsx create mode 100644 examples/federation/component-app/bootstrap.js create mode 100644 examples/federation/component-app/index.js create mode 100644 examples/federation/component-app/package.json create mode 100644 examples/federation/component-app/public/index.html create mode 100644 examples/federation/component-app/rspack.config.js create mode 100644 examples/federation/component-app/rspack.node.config.js create mode 100644 examples/federation/component-app/src/Button.jsx create mode 100644 examples/federation/component-app/src/Dialog.jsx create mode 100644 examples/federation/component-app/src/Logo.jsx create mode 100644 examples/federation/component-app/src/MF.jpeg create mode 100644 examples/federation/component-app/src/ToolTip.jsx create mode 100644 examples/federation/component-app/src/tool-tip.css create mode 100644 examples/federation/e2e/checkApplication.spec.ts create mode 100644 examples/federation/main-app/App.jsx create mode 100644 examples/federation/main-app/bootstrap.js create mode 100644 examples/federation/main-app/federated-imports.test.ts create mode 100644 examples/federation/main-app/index.js create mode 100644 examples/federation/main-app/package.json create mode 100644 examples/federation/main-app/public/index.html create mode 100644 examples/federation/main-app/rspack.config.js create mode 100644 examples/federation/main-app/rstest.config.ts create mode 100644 examples/federation/main-app/scripts/rstest.setup.ts create mode 100644 examples/federation/main-app/scripts/rstestGlobalSetup.ts create mode 100644 examples/federation/main-app/sum.test.ts create mode 100644 examples/federation/package.json create mode 100644 examples/federation/playwright.config.ts create mode 100644 examples/federation/runtimePlugin.js diff --git a/.gitignore b/.gitignore index eb31ce03c..e2bee9bcd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.log* *.cpuprofile node_modules/ +examples/federation/node_modules/ dist/ dist-* diff --git a/examples/federation/.gitignore b/examples/federation/.gitignore new file mode 100644 index 000000000..45507cc5a --- /dev/null +++ b/examples/federation/.gitignore @@ -0,0 +1,8 @@ +node_modules/ +dist/ +dist-*/ +.rstest-* +.rstest-temp/ +.rstest-mf-node-remote.lock +.DS_Store + diff --git a/examples/federation/README.md b/examples/federation/README.md new file mode 100644 index 000000000..2e8f578b2 --- /dev/null +++ b/examples/federation/README.md @@ -0,0 +1,35 @@ +# react-webpack-MF + +[中文](./README_zh-cn.md) + +A complete Webpack Module Federation Case with React. + +# project directory + +## lib-app + +Removed in this simplified example. + +## component-app + +It exposes UI components to `main-app` via Module Federation. + +It is a pure `remote`. + +## main-app + +The top-level app, which depends on `component-app`. + +It is a pure host. + +# how to use + +- `pnpm install` +- `pnpm run start` + +After running these commands, open your browser at `http://localhost:3002` and open the DevTools network tab to see resource loading details. + + + + +[Best practices, rules and more interesting information here](../../playwright-e2e/README.md) diff --git a/examples/federation/README_zh-cn.md b/examples/federation/README_zh-cn.md new file mode 100644 index 000000000..6aa8feaa4 --- /dev/null +++ b/examples/federation/README_zh-cn.md @@ -0,0 +1,32 @@ +# react-webpack-MF + +[English](./README.md) + +一个相对完整的应用`Webpack Module Federation`的 React 项目案例 + +# 目录结构 + +## lib-app + +该示例已简化,不再包含 `lib-app`。 + +## component-app + +组件层 App,通过 Module Federation 暴露组件给 `main-app` 使用。 + +它是一个纯粹的 `remote`。 + +## main-app + +上层 App,依赖 `component-app` 应用。它也是一个纯粹的 `host`。 + +# 如何使用 + +- `pnpm install` +- `pnpm run start` + +执行完上述命令,打开浏览器,输入 `http://localhost:3002` 查看页面结果。 + + + +[最佳实践、规则和更多信息请参阅](../../playwright-e2e/README.md) diff --git a/examples/federation/component-app/App.jsx b/examples/federation/component-app/App.jsx new file mode 100644 index 000000000..c8f771aff --- /dev/null +++ b/examples/federation/component-app/App.jsx @@ -0,0 +1,38 @@ +import React from 'react'; +import Logo from './src/Logo'; +import Dialog from './src/Dialog'; +import Button from './src/Button'; +export default class App extends React.Component { + constructor(props) { + super(props); + this.state = { + dialogVisible: false, + }; + this.handleClick = this.handleClick.bind(this); + this.HanldeSwitchVisible = this.HanldeSwitchVisible.bind(this); + } + handleClick(ev) { + console.log(ev); + this.setState({ + dialogVisible: true, + }); + } + HanldeSwitchVisible(visible) { + this.setState({ + dialogVisible: visible, + }); + } + render() { + return ( +
+ +
+ + +
+ ); + } +} diff --git a/examples/federation/component-app/bootstrap.js b/examples/federation/component-app/bootstrap.js new file mode 100644 index 000000000..8c872d14b --- /dev/null +++ b/examples/federation/component-app/bootstrap.js @@ -0,0 +1,4 @@ +import App from './App'; +import ReactDOM from 'react-dom'; +import React from 'react'; +ReactDOM.render(, document.getElementById('app')); diff --git a/examples/federation/component-app/index.js b/examples/federation/component-app/index.js new file mode 100644 index 000000000..d390836af --- /dev/null +++ b/examples/federation/component-app/index.js @@ -0,0 +1 @@ +import('./bootstrap.js'); diff --git a/examples/federation/component-app/package.json b/examples/federation/component-app/package.json new file mode 100644 index 000000000..a55d6f4e9 --- /dev/null +++ b/examples/federation/component-app/package.json @@ -0,0 +1,27 @@ +{ + "name": "rstest_example_component-app", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "build": "rspack build --config rspack.config.js ", + "build:node": "rspack build --config rspack.node.config.js", + "serve": "serve dist -p 3001", + "serve:node": "serve dist-node -p 3003", + "start": "concurrently \"npm run build\" \"npm run serve\"" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@module-federation/enhanced": "0.22.0", + "@rspack/cli": "1.6.8", + "@rspack/core": "1.6.8", + "concurrently": "8.2.2", + "serve": "14.2.3" + }, + "dependencies": { + "react": "^17.0.2", + "react-dom": "^17.0.2" + } +} diff --git a/examples/federation/component-app/public/index.html b/examples/federation/component-app/public/index.html new file mode 100644 index 000000000..432d5b45b --- /dev/null +++ b/examples/federation/component-app/public/index.html @@ -0,0 +1,12 @@ + + + + + + + Document + + +
+ + diff --git a/examples/federation/component-app/rspack.config.js b/examples/federation/component-app/rspack.config.js new file mode 100644 index 000000000..64ae32313 --- /dev/null +++ b/examples/federation/component-app/rspack.config.js @@ -0,0 +1,68 @@ +const { + HtmlRspackPlugin, +} = require('@rspack/core'); +const {ModuleFederationPlugin} = require('@module-federation/enhanced/rspack') + +const path = require('path'); +module.exports = { + entry: './index.js', + mode: 'development', + devtool: 'hidden-source-map', + target: 'async-node', + output: { + publicPath: 'http://localhost:3001/', + clean: true, + }, + resolve: { + extensions: [".jsx", ".js", ".json", ".wasm"] + }, + experiments: { + css: true, + }, + module: { + rules: [ + { + test: /\.(jpg|png|gif|jpeg)$/, + type: 'asset/resource', + }, + { + test: /\.(js|jsx)$/, + use: { + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { + syntax: 'ecmascript', + jsx: true, + }, + transform: { + react: { + runtime: 'automatic', + }, + }, + }, + }, + }, + }, + ], + }, + + plugins: [ + new ModuleFederationPlugin({ + name: 'component_app', + filename: 'remoteEntry.js', + library: { type: 'commonjs-module' }, + // Required for async-node remotes that load chunks over HTTP in Node. + runtimePlugins: [path.resolve(__dirname, '../runtimePlugin.js')], + exposes: { + './Button': './src/Button.jsx', + './Dialog': './src/Dialog.jsx', + './Logo': './src/Logo.jsx', + './ToolTip': './src/ToolTip.jsx', + }, + }), + new HtmlRspackPlugin({ + template: './public/index.html', + }), + ], +}; diff --git a/examples/federation/component-app/rspack.node.config.js b/examples/federation/component-app/rspack.node.config.js new file mode 100644 index 000000000..cbed2b56b --- /dev/null +++ b/examples/federation/component-app/rspack.node.config.js @@ -0,0 +1,71 @@ +const { ModuleFederationPlugin } = require('@module-federation/enhanced/rspack'); +const path = require('path'); + +/** + * Node-targeted remote build used by Rstest's Module Federation test. + * This differs from the browser build (rspack.config.js): + * - target: async-node + * - includes a Node runtime plugin so remote chunks can be loaded over HTTP + * - outputs to dist-node (served on a separate port from the browser remote) + */ +module.exports = { + entry: './index.js', + mode: 'development', + devtool: 'hidden-source-map', + target: 'async-node', + output: { + // The Node remote runtime resolves chunk URLs relative to the remoteEntry URL + // when publicPath is explicitly set. `auto` can throw in non-browser contexts. + publicPath: 'http://localhost:3003/', + clean: true, + path: path.resolve(__dirname, 'dist-node'), + }, + resolve: { + extensions: ['.jsx', '.js', '.json', '.wasm'], + }, + experiments: { + css: true, + }, + module: { + rules: [ + { + test: /\.(jpg|png|gif|jpeg)$/, + type: 'asset/resource', + }, + { + test: /\.(js|jsx)$/, + use: { + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { + syntax: 'ecmascript', + jsx: true, + }, + transform: { + react: { + runtime: 'automatic', + }, + }, + }, + }, + }, + }, + ], + }, + plugins: [ + new ModuleFederationPlugin({ + name: 'component_app', + filename: 'remoteEntry.js', + library: { type: 'commonjs-module' }, + // Required for async-node remotes that load chunks over HTTP in Node. + runtimePlugins: [path.resolve(__dirname, '../runtimePlugin.js')], + exposes: { + './Button': './src/Button.jsx', + './Dialog': './src/Dialog.jsx', + './Logo': './src/Logo.jsx', + './ToolTip': './src/ToolTip.jsx', + }, + }), + ], +}; diff --git a/examples/federation/component-app/src/Button.jsx b/examples/federation/component-app/src/Button.jsx new file mode 100644 index 000000000..c5ea047b8 --- /dev/null +++ b/examples/federation/component-app/src/Button.jsx @@ -0,0 +1,36 @@ +import React from 'react'; +const styleMapping = { + primary: { + marginLeft: '10px', + color: '#fff', + backgroundColor: '#409eff', + borderColor: '#409eff', + padding: '12px 20px', + fontSize: '14px', + borderRadius: '4px', + outline: 'none', + border: '1px solid #dcdfe6', + cursor: 'pointer', + }, + warning: { + marginLeft: '10px', + color: '#fff', + backgroundColor: '#e6a23c', + borderColor: '#e6a23c', + padding: '12px 20px', + fontSize: '14px', + borderRadius: '4px', + outline: 'none', + border: '1px solid #dcdfe6', + cursor: 'pointer', + }, +}; +export default class Button extends React.Component { + constructor(props) { + super(props); + } + render() { + var type = this.props.type || 'primary'; + return ; + } +} diff --git a/examples/federation/component-app/src/Dialog.jsx b/examples/federation/component-app/src/Dialog.jsx new file mode 100644 index 000000000..fb3b5a25a --- /dev/null +++ b/examples/federation/component-app/src/Dialog.jsx @@ -0,0 +1,43 @@ +import React from 'react'; +const wrapperStyle = { + position: 'fixed', + top: 0, + right: 0, + bottom: 0, + left: 0, + zIndex: 2000, + height: '100%', + backgroundColor: 'rgba(0,0,0,.5)', + overflow: 'auto', +}; +const boxStyle = { + width: '30%', + margin: '0 auto 50px', + marginTop: '15vh', + padding: '20px', + backgroundColor: '#fff', +}; +export default class Dialog extends React.Component { + constructor(props) { + super(props); + } + render() { + if (this.props.visible) { + return ( +
+
+
+

What is your name ?

+ +
+ +
+
+ ); + } else { + return null; + } + } +} diff --git a/examples/federation/component-app/src/Logo.jsx b/examples/federation/component-app/src/Logo.jsx new file mode 100644 index 000000000..d20597d3d --- /dev/null +++ b/examples/federation/component-app/src/Logo.jsx @@ -0,0 +1,5 @@ +import React from 'react'; +import pictureData from './MF.jpeg'; +export default function () { + return ; +} diff --git a/examples/federation/component-app/src/MF.jpeg b/examples/federation/component-app/src/MF.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..b8563c58810f6caf141686e4073ade045072575f GIT binary patch literal 295619 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%0AuL%yvzZ?Z^)1Nz%K7g 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

Hs)&BHTQ+|hU15>BFkp!S!pk>O}e6?Tp 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 o-H>(+?6@zoeeUr&M)tPo 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 +tGxtw^XAFG>@5 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

gKLTNIVe9Y;4zM3 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%0Dqj2-MvzbGWGt}ZkME!F%Td9R~kC~OGE2FVR zIRHhoZ^7|ELg6c1n2l^lj`F^5r-O`6=B?L0^UpjQ*e8Dn-6?&+;26`t*`JZF4^|Fa zc`bjkFde@s(wop-8m1oGYw1ZfhKwN!4459YkikK*hi5?PW07%9Trhi)i?-UdcUgCO zx%$H0K&gQP=kaEG7z~5x8n7kwHNSZ;T9>F@|In3o0_r zF0A@eb{#>yPem z=wkhRmQ%lbwP#&-(_#=KMj-nP#3z`1<&e0}dVi51cD0V#(+3Gt)~4#jqptXdYqu?` zu!yrAoW#|`E&JAgM0YElLDYT;w~nmGyj5?GEdT=7$_^RuUOv}3AN0qDyegD2z*}Jk z+$cWZi39dZk_8NDo3^Ab2=6lO(x_cHCp60~8`kj7Wez2W81iZzUVj5+12Fb{RQ{4w zh$4{#jdT4sj%Us^O0Z8K(C4qtiF~Emd{HDV7~gKx9IF}hKJ3l3YbEHOm|M-LB?q)G zZRJt#EO-`%ED0jR9IqHfC^9&bS*`5zvWk3chBxu&z-gskgUteszK0F)S(~J5Gp@oi z-gbU_LBBl?J3g8_lxOV#mrs8J>M0`$v{bQ*oDJC9sHaP3x4)JD3V5nO1X?h;G*!l& zeP3}AWtUSgi`1?73Hvb4o3%oU-{o94tg(dbkV`%_=vlk6@e$PBmI%KR;NjN^AD%c;y+UAL3F-~?LR#Y zCfD|29mfh@Yto_rEIoIN(`8a9`V-7g7-_zbQ*n8;Qy((#WU8)p7bgA(KD*Zv>o*#_z`}unznq z>V96_{Jie!R&lx?g%=;yp(N>*#IaxFy1pxu%M~&x#l3Qq-iYJE=xxi=$c5&>3b<=& zZs1jAy)1v0)zA2sw zT<|lSt9-?@=_coZ)7(mDX9`C*5*sJg`{efnZn53iarXHCSOL`l?Ev?RNA{jycY3PKk5u_BxG~ZMt9;GmIwY35${SaQ8&un zK@7y}zpRGV_v_qc^N}ICq`Bt}rV@y$cw!*JefZJbx5tfT4lji>mO5AgENKRVUxf!l zZYEtUv13GV@!J*@y!}ky^7)pud|#Y<7-Z>_KArGcpHv)t*XQkG{~UW5E`IGfb-BQ> z;vZ*h$P9|@^$Z9_4%H3Q;FL5N)?-A4FO2<%N6t|(daH)2FZUSbLW*FS8I6`+Kzchc z21C2=>9?A6l6iOtoJDfpIe3>VW1h2Ip5fkVPrq;2=QI*ppk`DtSFUJtugjoFT7~+q zMPJntfo-o*J5$?LQr^bfGQP>(W43VsS~)BAi>Z#aUGk38rSqy{EdAcigWHa;-z1?G z3zc}`kAT7*1`};pTRT;y9+|uGV|DJ6{>cqUjZcw+O_cQ6@wsmnjgvj*uaOW$#+F8$puun9{um=~u}t z$#oXVKfuWg*o()yN5x~^;uD#M!Qs|zD8+APB7a!~A@A>P1vx_qH1I0bjpvx&UL{AR z)-DFS=p2>_=ef`7)pN4-8H8qF0(gO`0;P;s8?4B0hy=k-xTeq4s?Pe%&?5uAT939hM3!_uiwccc?+@Ym zZ$oej!{;A>yQ(q z^DWe^9T}d4=XNhGqTd_EVRXf#DJaE`X*S&@}96Y@zhv2YX7Vi!7 zzMet-W_J{=f5m^Ub_#)|#U^n6>602RX=oc6NQ9`@XKot{OK4k{vy1g7Ef&O(_+bj{Ps}#QcwZ^vQQrQL$G1YZXwQ01p!4ObSf_y;OOH(T zbC%DADMlc#SOL}Nm5DFGF&cHA)){X~vsS@=Z+h(s%e@NUTgi0G_~}shiCjoX`@K_J&*#ahg9AO+W1+fZn|-3~)`0Wa+##(Kf{y=;QwF=v{1RY zhy3Kge2Y{IC|Ozqi+8-GGu@kmtFi6EzcXiL{Fs-`QUF(g7XsMIldzmXO@g$u?fmWp zAg`o@bbJ&Gn8aPWGkYO*0xNL13VBe+40{t75Cpp!uR?A z@J@dV$E5z>9z2T9T*M(S1XT+~WfL{yKcgU1PQe!wGXtiA>uS5r|2df6A6xIB)<5RT zPjsC9t~G@}_rWroGXb^HCxB<_V?XZkou>afH~;%dHH4yqVLrHz#&8@y2L`x)h-kv$ zyY~x$X`vAOGoCA_VbVS!hQW0*MCw5Sk!Cl1^NcWbv7LD zE^mOQalb9C_(~xA_+@L`JmEjQ80`yyxITyhM9i*RBRKOQDxkx+n=zJtbqSfz zG9n3HE9wb!9r=exU#fAVc?E~deex$=hhJubb<2Sf!I#It5rII6;Rz>nxzCyjpz~=~ zc*yWETq^L#Vx~UamcD1%MAf_A1hD{};qmKC*DdTDxXaec*%>PJ3antQop1n^>AcZ3 z8;WUt1nqqT!McYw=Zo;b0uZ|hgSz!D|(9l>xaO4!q8*o>gs>|@{DFWUL`LfEBOpSQwnu&#IVjm zVLH>W&@WGYhw&$1})Y_U=jUV!rwf4DKhta(r?|s%lXBkil znj)*m&h_lCZ&i(Kb^3tRsS|g zkr}$-5WKI7k4C1q)pajt+FGo06F1A*zAud8w&Qb2(}VKfT&|wD$Kh>i(6{9a=$BR4h9lkooC(dnnK*x2 z>aN;fb5haOk2V4V&c#_j96GMT7rwu)ufy~*o%IYldlz;*OR9WsNO?6gsufhdPt9nkF0Cv;XcVi-lwK2XFTBA ze?TA{S|^Uw;wj~6qbeDebQ%#B&jO3Lt9>TPx;#*B8v$C@M;!2~E+pLS|&d zEjkE&wPCxgr@yH6^S9^`{v{1s^k^}p({#f27olBpC*XY}3#3DVF99?r`IAYuZ~N)z zk$M%g0hOUsy7knTFzjDada4*Yvl^>ak5;-~tw$PDraz-JS}y}B?7@Cte}au)KO{ae z7ruED;Ncpag=eNSJ?C;^GS@n2&xmk)A@;;IoBAq~UKgpY8#0Bc({wMSk#LH$KAWLq z;ymjPGF%E;S)tL<0g~fLXY780Egobko~SDOrjE$*jYlsS=P`I7QUWTXYE!rTQ~t8b#L7#3l1v+=XRoP zfPc|<4L)L9=kkW|oo){u{k_j@a_Ek5nkhHN+~_oZF_y4&?u6_ggjC$E0Y~<}c9b^( zwd_PnubC?a*q6EXV8U;!{^1==)dxU}8`@#OO;`ZG_3PX}6WLKN3e2W(kOiQ>I|8uW zH@+{b3S?5LtL#fmUkeQjUcHqRinvOc`OlH0-=4l!5+{q)Z%kth`pYt&`YZle4z2sQ zjjZ`iZmInlp1-X<@-yz45^p{xFzo(>w*2A_{vUbnBLq`wBTBaMQ@BA@JoQ5RmE#6~ z^fbZ(LfQ+KT<-~9xy;_+521>{Sa z!NhjD(vq9L0O5cVjqEJagPJ;y%56sXxrCt!>nmYS@QTF9cp7`bbl<)A3xxLshPjob z2<$2TBnfP=x?e}yUiztX867=)*Sy2yiLnLeo21*a7S}bD=Qy5q$i;Ey-BrN{XZl?8 z$641|8^p^ltCHcUcRswh+#{wm=6Ur1u+ippJKO)|VWJX^dBnI0YRhz={AAk@n!VT5 zjZlCI_ZIBaZu$xwjDpoJ5yY@HYen|gpnB0$zNlgi>Mn;5zW{(Dg_hcd%p;v-eWB== zGI0)9&HCg*F1@8;LnRjJ(FtQgqtHrt$H+YVb$!yC3FgrNJuV7RTY(alhk-cNozupQ zvxF={QIt37sh@JG7np>}aw>^L#0;xnS4kTaenA#s|oYRw~?>IT@yjq&I&h zN<)_}Rim*(Bg6A!5DN68McT_ef}3%FssA=sSY5s^4IQ6G%Wd*eguQU;ab zI+b4oMorn*F6edxy90*S!E>J7P~w2s0q;@DT{GzfrNn3Ch@Dk&#-n?v1KeQbbxEA= ziUfGg)G(Tw(YQvj_;6L&)Evr+I-MvHUkQew-r8x5q9DB|6kziGJYOn@u$31R{^V`)C@Gj(G^|uRNQte3GQe|e$+0$Nm$x!o5RQTm4M)=0ej<6j< zB@!h=W18XXX?MLI`XFw!T8Hu7PN6(^Z;%+gT_8XKb)b{lgQz-g6UYBsD3|W~4f)q9 zD3QWu2UM7TetP`0%K}=3JW)o=R?ORd=yD4zVK~DD13g;Pg)4*MEaKae3K23pjKO+E zjQbj|AI<6Vx=OUWu+Jg|7seg>Qn`5E;hKBN$W+nO1ue`P-@0WHn?18z?-cmJn?q8l z?P6B>59DV9pac)^5?q8Lai112E&QAV2?OjBh>jIfrw8-XKfcHc zr6gpIx7E&{otBK|q;_~ipU*(QF|{*WCw*qpgi)`rJb^p7k_No6cj6hrvP$ks-A_jR zDOtj^VUjqSu0MHT4~YKSoSikQPw?$dG3xEn3pP^~su51d#^!}_YuZo?EdOmn&|O?d zD_DyTcBWr7Ev@R(YB4PuUkJ1ZucbMpcXBq*=9?LNzl^(Nk--;6&gl(CucFovhu-M6 z%YmlaX<26T{#EeZ{_x15(Yz`S?Oz~bpgT4b3^m$s<-5&*tY(0yO{7R21=r!s%3CI! zh_@{)&2d;fME0fV*-8%t!@1K1iSx_AQDR857x#><5PVR|#ln+0ihJ1*9;@4e!9d9w zHdNiEEZ&OmnzB zZ#f?H0E2=?Awa{!g)}OP=_wn=2hgp~GZtzfTBg-uw%k$iZI-D%AM7a#wEHCf9gL`>Vb0RA`w!GY?J^tne>7}_p z;TCANZ#DD{`T_Do_?e!mEBX@-vQKx|#GY5bVg6sOo7bav$5f-o1&PZ3$QK=J-3>3u zuKBRfZ(LgBpr5XoH{&xSuwWwJw3*^VQq-E4mAnC_1z7$W`U&74jcWd zc7LWx?|_}76Z5s2mabW5r2PRGQt3hI8syV8Z*P>eg47k4h(MJRL*YPnz>03Lc`iyB zN1VCt8qwH|jD^_A1Q`wd8Ucr`C9$}8P$@A!yL{f38K`~3fR)1Vufj=)T4@bC>e^p6 zw=})+Ce|uV>Z8L^cg)mc=J&U}rqy3jwfe?=;9jfzmZ7LxKm9i#Zu+#0fRs#CohV7` z$VWnp)IN(2YzyPyWo zo8RRiM1mafy(nuq#I4vh1*ryK$vIK>pP0pU-U@evWX2VbGk++;t%tU1`Yot#uyaRx z$VXbC+Vzz!TF;INXNMkrVUhhLa1eRHxlLT!Lh-Q&Rq%|;J!JcQa^wBPT7q*GPZ32|kDkJ?f)N^}Ka$A#6U%6fe?eam4cdK2=zwv25 z5h@{qrb$Mg9P!+HGT1_?Bb@R1H~!*8mf&u}Lg*le!rM8TkN_FB?>*7kb#lX=LvE1T zo=~Y>5Z#p3yfbs6x-Y@nX_W`L)Hw^PoPq{7It`*pJ4cW$z&jMm#ri5cgdaQa8+rtV zR7p#rXu82qL}{^#XknwQ<)zr&>Roa=xeYw>hwm;nr)Od6WX80A)HfsNZ`xk@)0Q9^ zK4(GYJO@l_e#Di^s@+B0qwtY->-xN`L{yZ^n&`&852nO*(S%?J*8qrwiA+?hm3j^L zGycCG;w;NQrQL7%9NS2+{I2VPQg7q*Cq=Gaowd7Cl0-;6XxLnhbv)4b{8Ut~>DQ99 zAMolIV;~2Y+LJgFzvZ1uhx7;YwxQLI3?DVRo(SZHGlo3225(^uf?*S{5*-ms(TOS~ zF!q*%_O^#lF_o*B3sH;9*_V-*)GW`mPOQcnXVS59WA9^?iRd26z63Q~Amg%k)N(&f zrConk9Yd-K7jhRQ$9=zO;@rqmw-?0653Row*V*E6!eFxEeAcQxTgQumtDVPD?^P|E zs?g=)SC|H@WV+RPup>C5Ro23>)wDJvg=*Joo{iEZ300#7iT%PFHU0BG_c`n~79Mwc zvW_NfTF{>MEto)(RWEB*XXPZ6-_ceV@+{BxJkOk5v5z+?(px6SyRU|@IWd!DJX%bY z*s5$;9A76iVtw$|BC~F(Pi4U5!;#JK_6|BTeLDWJLJMLI@-yaT=hD=SJhp1 zL;{a-XOKgB=9SqWwp^ZtyxRP<{H57!i6No+y}2z)d>W~K7l@Wx_I%7}lT#l_v6R)^ z=Vui!^|X!hU>n|jPw_o3wu^II%p=kFoUGq|E$|>PA)L+$*-ieFQu;-lKzjRoqiCdD zqYX#qeq=rNV_~l7q#V?rZ|OJpp)A zzqN^6vNYTd+v<1P`c^A`Gz6^%QkonY@9J1>UZrt>mK?n6&t0{1-+rzzHF2)z$w_}= z%7wJLt&T{#C4kSGK z1#)^zhzsMsz8iOIe9H~=j)9U$hgA-I<{W%Yi(J{ot>1F*RGF=v$(TMF|9{{Gm=o`1 zGO@qRJ}=Xv#3Vu}7TP0Nn;ILE`s-?cfO+6eGlI+uZP0fLDXz@huO}j6t%4`bcm)_6J{79L22k+Wi01{E+wV7EC z*ML9eDyV?&sT(F?MifHk=Y2)h--d0j(+E9~xV$L2L_8E>Xe!sdKWSm)wXVNqR9S^b zr8VJ(-A|^EJ8Y{r9|!-5jg2fWaG3TRDp{OeWcx!lt}-lF>Yb#?_osTo06oZuy3!slcvwnJESY^G2PH8uh*MyqGL`Q~9|Vg{Q%f@l8#$JeJwXb_K&Q)?Ar?Z?SEM~7^eO6>`1jQ)-bJ5gR3LMf3ny`FUUS_N2lq?EH7XR z|FO$zkjP{Od0!T{-Qtn2D$`YQcXIQ)$KS#Z`iE@NtmOXsh*j95_T774+5rXL*Kb_E z%~$(cWeBOL#X0Pid8hq|;5&A6Os<*AA-VhR(Y~YnlawGmA(_$?TclcPY;Qf5yV-x} z#cjsUqmPi21hW?3k#?C*rO8ll8lc$wl6v=ILk}}|9c#iN%_bqcQWWh*77zn?en@I) zvItNm8wG`c{=AR9wcaK9wD)Mv##NeSEm`LdeRMeDded=i0KQ^>jf-Ajr~ujS$mXxj z=%~gP2@J1(K zN%_xugVCR6ex||DkHlDRogQDpfj?R;B6H#{a#%+#jY{5Un^p&!uJV>kLkvtZ#~p{# zew60HYvLzfy{AVj1NtniXK{WbsO6ATXYtjGyDdJQpnEB6ImMHaeC6G-+q?jL@=pvT;+88{$G14#S4kQewP-gIj&$a&#NH*uN?KOrS?Z8k&n9-^ zo20x1kCc0AELgo#sF)>fBX(KGX%KSKSDz0Ewxb<_T}QW#-PI>J)jjT4+hUXXH(l;*t#_KP`gpm~AdUMIC>8SwDGH@%SI!1J9>~DC$f|YycgDNZ}h2 zWsvc!?(n_HL(Qfe{$tzk5*8bI1+C|n6r@3$?JY~S>=`fI&6>pi8m z$8lj)S>{|CV+OM#YdZ-q@@p_T4_LpulI%}xdh5J_@3N=zJ-z+zxBCul$iLkNh>82s z7dpjWct-r~%O)p^bAd~qVENyTe&i#jJ;qcJ2l%c#Yf#K$$xmPTFAnsc^>8`Y#6{G3 z3LD!=+N5j!9l^(4i+fv1h=z#K}KJ|S)avdSu0#ZI7`;Lk%jx=pz8g)8YI z|5v={1QN_>DD{F#faxTI{dD!MfEU@5DHb$d`rt%=wzR)I zmnLzTNj3|4+lYop*PbU+xIfgE|B7V z3y1y&yL5q!lIy&uEcX(SegVN- zhSjb2Ad2%eZolV0k{;h6F$^5LK>lo%4Eh76fZN3oI750QsaqxwzgtdPyh(ine(OH6 zla4VRZWh8i#?rWy77kWkD`|Z4-G&aODKBdd=ua=VXr-PnX-*jb3OnuC=N>c)+ui=$ z$r5KNITb$#y6TZ33phh_T#5l@F{b6k0|c3CK6)l3xw+p9*oRjqjrUxM9ev0m(;=LImamg+5BWV7WcuZ(DTApH`wgx}^t#R_Uh_h_D%CfDkmLT-(k2?1 zE|A?Nl;%cI`DN5>7*Z7&E&OIzv@j>|oVL5EJ`ByBPxunWHh9A$Az?*Keh> z^s3o;_0xmXx%>Pg#KS&{i+7gb&*Rpihu-!tN&#>ue`lbYDFeU53SdWmFeE5Lu+)>q@Yo zq5?=Y35S(exp$6OE?v-dy%dy%QLZ~`e}SOb z=(6wU<+d=PBxJv`x%-9rKF-)FTubjkL!+x*@7wD*NKWSxAnZcfw%v%Y$+ugbCLwlk z5Y`Wk57SzW3p+kx{~%cVbIhGq+NFPuuwiGuUQm2qT+g?~AG8epYFR}WwErSbf5a7& zkFM)L5LNGdH=EQwGF)Q%%0q82L$JIO0}KCjh?BrA%qJOPxHVGSmkD@(IUBzl%jI`( z_UN61A@ka7kr=kts5}Qs7;;0l3@3!9>}s1UP`I@FF438V#Fn1$vM;EPmhqn7zL;O` z7`Q)2-O_A9N%)hAd&Au~-&CuyT6y2sm10fkAD&+j_NMAoeVyX)`xe{W_Z%4D+`G<2!ncPvYcnZEfA zr>b_mp)(fvOZs4!f=X#vVw-g+17S&P}YtjAouUy18Fm7Z)@S&Wj^R3Mh7il^DaI}>d z6cDa2yo+-Fx2;W+=k6u50|&ogt+pftcQ*3f zYY|n$HERn+h2tk=Sfcii!xQHKMErdTtWB;il9(->a@%Sk?RBK`0T(IMyDG-?>6@bZ@@AlMO{@CJD0koJAbRd71~hIsy;= zIHM1|YX}nCY*y*qE5w%G!diY@=R!j90Tut3nh&=di~SsF^kPB6{eL0JPQBN?bej%Y6_YHgi#%@Mv>nbn_+~6iGihm%3B3~i_HB*I~>KFUyeW5eB`6Y4F2XnqZ4gjbX9D*uXtKD zBCY=38%4T)&zyPO$_78uPp8du6pk4NrvI6nQ5I$J!LkCr!G? zJ>$?%+tN?=r@$LA-y)Vz+JFW{4!W~YKUMO%%RSVrx>l1VD4qX<@MDP(#iaghfJtp(Qbe+YP@^B1Z*h(x zaL7wcaCZ!k=$d}$OH3=J%Ywu(6geT@?XOw7#_eB#co>|)#r)2;#yvHQ=(OOpdyrLu zxj4%0+Mw>iE91%a{B-s!n^+}98_Tjd#(dZ}S*`I3`yYn+hMmt!A0+)`yh*QLCPHYz z{&=YS-;IrQdmBh*JW+iIudl&6MpMaP8#JZ)!yk0l8wl8jDNb z4WdKcm`MsHB=05vuJD&fVG|c~uc#i92Xx~noFhFkK5I7qpW>N0PB|ja9H+H4dmF;@ z|BTtT16hM6I&i^c%CEL|bcFNY*IggNxZ7u-?;ECa#fk)3_2aASWk1Do=V6wRivgk- zE1ueWo$w;HTDPHSA%c6ABNcbHTSY9*=Dwx!sIvW39r4_E_=SC3xi^(j&M zWf|ZB@4pakY1t%em9P?j7t}W1+9c+<4k6exKI6iFQ$zI=@5Rin)=rXcOvlI_QF}At z*SSJQWo&faT(7P|yNm&uy)oOX#lic$D1ug%>GS??H&Am%?Bi$>B+muqBAzUEFA!Uog^C9|K)YLsJit!7`_ zUl#P!-8F0Dx{eGT;dgK34DDvV`nBOEJ9SUP@qRmNwQJHx&CXlL2F5y98;9*>nL%%l zePVL;VsOHFkxe>nZ|Zixq}K{1TPoHraeYnqVNaFP23blw?Zt?308O2C;^hz(^(Jc} z_PNubj#jbs!@}8rcpvJ-5?|mEyrv=(?R>SXBNp|JIqbVV;eouFmfNc&l`yNAf@ebY zNB!IR>_jtO6S%8b((HS29eLyH>a0DpB8gR$J#!|!3pq&l+o}niK<6q(g7AomcmxGF z4hDNFa$I=x-gtiN6<(~c*zCb}0)D0md_6Zn?AAg~G1#W>|#bym+p*aUz6~{kL zZ?!_wR7vXdNEg@3 z{SYrc@8ZXc)t#avhmU1_Rp%%H*u_8*>H+|8lENi%$ZW|#Z-p9{CEtO8Pd@(Ryx1o~>N?S?q+mQvKq zdl*)QgGh@3o-VST0{qphu5|F>Jx?<`HUA+$zrIDVOiJlHK zhu-qi3EC}(kF^!$EdD#O^nZLO>~_}>Icj#&Dk>$*UlKd{DN#zLcxiX(tbG!hBVG4# z&Gaj>P^SSSdQoZpBu4(vZXS9CGH{j6YC~l4^@i=_KYunZ?TJBdWQ1AxZtP9(=yvoPSGxnJPX4e;2v1$@p@t?<_X-z>o1V$BFGD-?S+AzCiIE z)&2t=xPA3I&M3%{jt`>+Lp%{8@wd$nm=(Oaq=t1q6mexuxS_WV8=&e0&6PyPFL72X zHb4FNpk8Lr`d1wxyB>Sxv1w|TGXC_B6=p(zo7!FFs@h(;$4?GM(vyGG5kJPa-t@$> z*N>JdDXbU7>KmfS9c9&zO&`6!)?F3pa3hcK1vqy;4m)jraB&#d_9)4cl z^VzNP_>G~#zI5N!le}7`xAThS?d)Qww=qCEnx9Goo=R)4Xx`-v(WWzVZ1$x5sUb00 z!qMB7*C!PPkL;rOmtTXnYrIxSkK>(p=4+g5L_EZL$`1hKIli&!FB|4O(2t*`>zQ8xWVgBR(NBsA!?4C< z(sj_Lx=CvJhrK`AoIt+U27}f+68nJ;!^w`KxI#xqmp@e_&t82OZs))+G`@CHG6^eH z>=}5mA7l|a>|QM>SUkKHl)8A!K5@8;y7FZE^F}da+vsjECfz0n4QaoA=iP#qjU$i} zJvYME*|hqBD{p^kP+ay#9_J;X49gg5H@&XX8yU3bxPQOE58N&*YwW<8WYloN^HqSdQcJ{~uqBWM5=Gz}QdP5ch^ebKP@q(NPqUd!{&AwtwT2W$J#reonV;r%_JCZm?CjEY)KL&192M6Kh9BG3C;N`9+89 z;X`1|m4p7^-U;2{cIsNu{IJ7qquZ4jP8pDfIM}~&w^;LENc0n#A!++YvNBv!c;vs~ ztPyFKML<;**zqg{xNc*Ep~`#dpzwE(=l19WYnQ_q3@5dUecCjaS(&U zKHr+q|F-c4p9p>cYLN!}0WxUUUN8-g1tzJ2Rao;cB_m%}tWW3;?RrGl&K9P!Gu;}* zrmWCwx+4z$9Q5iWu2t5*18J$XtRm+8HOIZ}Dw>r`6^j>MDg?%k zIvY6ckZXxwcKZ`FZMd=v-g|;pxJ$uHX+lyWjz^)HTwswdIi3I6$IPtl&j?4K8NvQW za`hO;)hrt58P4sfSH%E5iAYg1dFUmP-mP321x9cA$;480ZJojF?)%KI@QpkJ$8}ex zG^>O=(I}-?-`&j}OJHF})IJ*b-kr}ce4CLW`IgEc0qMIaSw+1`-nf6(gdKunl%)kN z7jjUCY|3m1Pvqz^d&ROyS?qJpW>0r^ zxwPJ2e2!hp(bh!LC zrAZ?*f$l0G%eqf1+1t3eE?Mco)|1y!J z-CBC~qFcAq=Iwj>1k=k8f!Zqpccz;m&M1U@!x&FaWh6{ks3$woJmgonZQMgM3;^_o-d_^DQ9?+hv$`Jdkj0JSM0X{ZYj{%rQbh;TSHNV3JS+v& z#J{kg`1oJ%$2PNDE|W8sOzS&V8H4&A(Zmc};ug`?f3IhPaieWN{{pI2OJeVPHBb^v z)xF-by~rZ7#yCMq2qdn>x-ELEHb_M)U`B2YV9`0n{aMqxnaX_KxW8LsG^n$cB>M<0 z8-w1tWSmS~=$`k-jQp0W?JQk5PGnBQ0q%kCbC`4Xmd-V3FCf=~{-oOVi@g1bXFYLD zWbzGHy67JrdBd%O?hb3RU<=D53K56wt}S+Q-p*_+Y0YWgd+ zg^isq=-f&d9Q7r@1vRvI$HZE)OB-JP#*Kkx%RM&8G?04_OpMu3KyN35^0W6pT*rJT z2hj{q%-r)PoSm7psH}G9UP?w-odtAqbZ?yoO^d~OxsY&Cyq+i>^)VLil2c^kefmF5 z#YBpXH{fz!j{G~LcUT~rQ>XAF%l06d04h`XAZ~Fd`)qaNLi8d6y6Lz%GCzS+KWPWw z5W$aN++D*oH!QMspI5NY<*wBK;i<}g18TRUwId&KWa5Ol=TB#F^{VQtf8ZSq+3;D} z*^SzO`~rBpJ!CTkBZli?1AJXVy3Gs#bICRQAKoDo0L=K2(%k&ne+ry)-uxc>Tzv=^ zHo6h4h+mwKL_&BM)r|j7$figIIq_^fG$1(murpB(o9UsL{|+o8iGAipHjHN6BhDAt zANcr5F!G<3IZPEQNl&p^dt3ZWu1uzW{?G%coXooLJ*|mUwM}>zE4n}($9chf2d^r-X5U1czGJ-cKNf(QGBnbY~PFXo0vmDc+g^{GRq5Ha3=z>IUaI> zL4NmL<$O;nEIr1z%mL!mi0Teqd@|@HPaW47%NLQaW zV4J6)qt^B;M7@X|@XeH#uTd#HDBfrlu5_KN+R)5g=VceB`E-F;T9ik4u#BbRFWfU2 zO|My$j7{MPZl2vHeWnu5T+H|m_pAXP0ivnJWUetRQEeqhvG1}iB>uY7PI!Pl7=qX$ zXcw34>u?0q(1EGy4_s7zZX>kP!MKwPq*}@KHk1C1+qiiq-H_(5&go=Yeh(k_(?Em5 zw_fSP2(EhjHw3z!cil~wj?-)R>BXgcJ$X0No^8(I{UsQMWr zbKh;+N>J}8&aQQJJ0uE=sK3(5E*M(U)AExARLej%?E6)ftPW<;?|a4!Hp~LiR={0A zp7yu=h(puF))yq#zgOG5aoK>n=pG64A~P44oK%PRf&fWA$Z~t5lsSS5f~oK7PLU^;t@b<7!*qaNbh^Qka%?{xGp2*<@Him^{*1 z*8G_iQ|t0nw+jc|zKnyvI$e!=z0*;Azf5ODt|DU!2laJ~v52i!Vx9qS)-HyGHbYTz zz$@?SxNKtj#B-mFe|5WMBiD6(U}D@whv5KkrS0?r2He0aO61I3~*UOg*YpReIIq zMJzG0uTr=)%7vy{zuzfn;Zu3&ApH(z`P8rWR&%BYN?vmW5^F^b4YgKTmiU<5ZhQYl z-kGtbp^x_1H|AYVrd?z^9Shl{Fa>ePe!mPsBRZEXRm-+g9xDtrCBB_0f>~Ymp%7i_ z{D*N2d+JVXW=Lu2J6XcrzK>%3q$;cf!@x9QutzsNisGXi){5jIn1n>waUID(!{G8^fS9UEEcE-ko1`l3%F0~AX#!M#~b8qYc&bUJ!eK1pOIq;;S4yPg&- zR;x%D%WBH_Q8UH#H#~^tZgQ^qI9cn|s1vO#IAGeGI5d)k~goztdXoeQyb#>UL< z?>XOk|AxJ4E$-QlR->7G&ub^xg7h`zfqB9j|Cf>XFkVqsfAz1wz1%}6>Q9VS^?zLb zIF9xE#@Hkf8KZJK*eH7|$=V7sEI(#7>6dO<_HH`C9}WF2IuP&%MG~NiDoUB6mvQJf zb~G~jkcPKe5Qy$=afeVys~7LrK5P~+hnjFbm;N@_qwExU5hJDhZo1#y);C}1=e*5* zz%~2)T%dkV-r>hs?ndPm4TlI#3(Z1KPrwuO4Q596^F5C*cbK`UNq+l?c4IwJyuG0pP0)xSdXisVeSgs$ORRrcM$bhL%<-nZ+9GAC zYo|q~?p$7Znmjsd=NuVWo*R}?^oMl$29&}hk*m{0#_66v(`nH1{Ap7SSQOXkX+-z)VAn8p*Jd+2+ydK1J^$2#ekUK z)cW|8O*3zTRS~MbXKy zzAjoPr3t3ar3iakQ$ry#ct1~#_Kyk?VS}_~9jx~J^+2qFq`p1KXAOzhN%dlnZt=m# zdi=c%?{i%8UKYdnAy%wVJ+P=x8%z&#D$rO820@Jd;k<(~=Fy zX;}Fo<0rnO+UUh{#M*qAS_&+{AeSF8rTJKciE?TFHD}o~gYVADLQ5 z3vO=gK_!G}qqvKe%}EkQuLFZ>uJPB*_~kL~4o>IXr2emH`B|-mBzlBQPvKhmp62`* zN1)}?zUmA7U$n?Ivb;ga04B>e5L3fsDteKJyhof89+Q%#C?Bs@E;vbI3xpw8T zhowA5rfd=eXMR#np62XRwyFLv6Z&K3VhlHfs5h@GN-uj^_dc(<(6;rdfWpN^Cooyp z+dx>Zxv&4}t4fOaIKS278d#{Wn2)UXhhF?GSHFWC&|7C?)8RjZ>830yl?O;{+&)!C=WbQBhpehmm<=c>k-3wlhq55 zPBVMeeZ$RFxW}BQ?tT`Y=apWR38e)$QM9LY41$Yjk?`lp zvuYln`&Yxpg4Y4bKRh)lS4 zM|d;d6H8_evN;FTqoaRM+hTM7Q^d_vXe+GcTEAOC3wqhZ)fK;))l%{@A3fy81uA5# z;m)cD;%^gG2Q~;YD(g(~JR^Tqy3s~YY?BSNE0I17EP0vzlS5plM4PHVIAbHj=Ifna zI+l7F&g~}=(Os1Guigdk`cDo$!TCjM(+tMTYU_D0JhRq~$xAxqB>hN3DEdx0p2%FL z_(O2JF2YzMf##`-8q#z;Vvzis>;-!V>`kD9o>pqSr?L=OFn_fu4$Ce{BmNIh6L=RW zfH$D63GfoFY-Bt5{;Q!4vIoJzm%DyI_K_lTc^5v#ar2|uw0)^}+pnG@FMLLH{py|p z2%Ow!m^(S+nH4H9KoBUw93(nE<=8~Tf3z90E}Bj!ZtWiL*e4?tc(4zV6hjta4+wD& z0T4p)!9P4W7z+prKam1u=4@b;m0mzyh_}4lntPV(cO5tU6TWtL6ut{;`-=wdHvlJ4 z4ZbEs-eTeCY_g;Oe{=uuAG<4ZcUTbi&x%|+b89-|U3IX#apmCCo09v=5^24pv_pZc zTAlAn9SltN@}vT)Wlj|djDq_pU3XHhxDCac^ zjJ%#4P?^$wet+qytUWk}0}&c5!FWA&Y;{OdTJ~l;_N`^<#9=T1$P>4+gYB{w3*2P&k(<_=^;YgZQjN zI&H<^xzbg<@SaJ1olT_<^Zr;|QQ8+dSy2-Usv4Y}{Iwjyi|q?uox#1RmOrE#1Lsct{$6dJpbMGX0!!eFHY`+VkXAlk0Me0m}(eh)3B_kVt0mz|f;d zv=&dbrLd%zQ~fj75Ccuyw#<#t28s6|00slXaA zV&M9^D1gi;>;6A;j7MV63uJE7B|X4=pYRAjwLJl`*dGIMW+-J$ucm7ENu%a?!eEub zdnb~Qp83oS^(KCXTU}lzeLh!_SL9%lQL18co{=Ga?Chq<9vCpfoL&rqBp33`!oMO+ zSd`JLyEm>E9+w)zeKS|RwtK3Zs8sNTg0naqAd&t3w=Ve&O$|XLC!<646Z6A-0W5aO z+HAVN9Ue+-{H$C!f_<6k7(z}B)rO~~nMo}D3;%i#tsM^Fhv7`dRW(3{SWUU#?tI(0 zrk?M4H15fe`UbGNoJJF%pwNOF10biYz4a+cRPEbFiUuXQ0h`Md_G&YaX?;zP`rZJ; z#<@jzibPiAPL0ZZ~QgHhYwI}P}SjE6Eu&QEyVY+ z_yHJd@w*R_`19FS=DF)MYF4~>oQ|T0-?2IT2CBv{o7|3(B~?I>QzO>}UUWdpNbAZ z)#Z#rsa|?{MYv~HY9O@X4<#!{lG0UjXk{5(3$#Q@$fzw2n&|I-BzQ(H4p)@2pX*3$ zvI3!QFq0rO+nMwzE)x=_C6Ip6I&o>IOu0`##?A+@#*_8pPlDc6iXcqDW3_VvN_rwR zGoDGx$qzH)doPn>7|c2h7fa+wXMAi2Sid!=ypa>^ix@-G`mI);fLg_v5*Vr5mDOEt zsp#Y$eiygA+`m3%k2{w8B$M#rkD-Oj{K+=$P030)U70&`u`QY5<B}1GBsfSz z`n)?X$+$25J^lE!H9u76BI{?0Rs9H*E;|f`dVc&peXhqP&s~6?`w|KnRP};rwfaZ} zP1tI0+l4Om(uHU0>rKUMnrCC{)^OiNc(4DPUQS|tL&@j(V_}pP#&L)^dMiPXUeB$M zbhf=2<9^PM>bPzz-ahYT2~nmC^jtzJMi}PDZFe4aS;qU#lOce}0g+n0h5S7VaGn~o4lj!2S7fI4!;EP7!+9r4p-}=BP zM^FEZRNcGoDPPBC$QK`S-7W< ze$QZZ`y%Z>M#5L9MKxBX2+G2Q^E_9S8~>-smsqH z8KcDYNspmTD|#cz?_|+f;y5g*@6cQAwgDZ0Fr;yM)Et6+>Vu-OBlVmEO3WVj*?R9a z?*$Z$q&b6;ZI8-~o+fB8Bp(@vbzgrR`GgI|3aklE-0+~#)*}C$fxEgzH19Uj@4N;e z&ai(|jWEi(z|BXxHyE*A1l|^1Wc7ZG8L|lrhd4vcygeM~vE` z9;1q@fb=a6j|(?vC^-jVO-8e-AqHuUnwx^yD~5bzF&Bm39ggFd@}w6y=zmX(loa4T zLtpt@3I?FJeSIzm?zF-2kj4Yyi20xvgYDXJJ=ul+jV(DQG@9P>hNK7`~tZs3C8If!F*On2Y)BT6>~XDCoCIwqO0xm9J`OZCDM z4d&&F5888*$i+~->@~dAhsPBTo{rbLwBsSY*Y!6oljhrKW|;87Q}4h?a>7^so%UaS07~9QVFic)KF$XL zxyaAQwae`jKH6iZS3lM7tdGWBqJ%55t&v2K`^EZH` zZQTY@l?7#%%k3CoCP%O{yjSKt^yN~U+Uh?3W=tCr(TG7>8o1V{j&=`8+Lw0HdMe34UnIfk zSab>=Nd0~)S`Oor2aHnlGx_3{d&vBLV7gDO^88xv0exNP^t&1GJ2bk<-xjR|$o4(H zJG~AGnA9}tx8r|D=V$d1M4wkPS#~~KyDNZ51^T$7v>5-o5sV#&Rz!lQ|TdL zII5GjN-}xYOJ!vTJ)g)r4>&}ahXVwy>oecLq!VDwlIm?_#H zNfA+k2!6=+W*{KF3tUQAX=^V3fH>0r$>N-)X#~3C1&MyZ5$>B;*y&k$2#IPQOAxE@EJ`UT?iqHNx*MV= zoNmNKWZ`)&yxbe`X422bQkT{)_DGhqfb?mv%@H=l6{%WJ3^Y%&1uGj-XE;X(e~>!-P@+$>mDv6|zC!*O{Y~y%qk<^(mv^W)NG6gd@I9PtLRgz( z`Bc>rnOhq)kXKJ2=ewqFEoSUnESx+(PJb!TYZ|!}bKMo+F`Hg%for|Uuo$`aAD`x8 zqfZ3&g~~2w)GUVnz@gC38B#200|}B?a0fQ6OgRFJHfz6d#9S? z#r+qU@Elx<0D*rfHbgfl2%81}{6IEf5{?;?NU8@`dhXbZ-T^ z9?d=cZ6iHvsKE&puAbJzU6wr0%5oaLJFY(0*d7IZ3Afs0Rey3^*KLDQB~ZQiB9ycw z6pY{`y%OEhs3gF+G%7g>C=tO)S%mbShzFVgb~c$)p-Wfo`j>teWvK)h&aVWoZ~ zQ!gGDqwpG<3A7%6w~8!okP1sWnwwGPch-b)x#II9RKZXN7_?;bNUc=QouT}5t>I~H z%lO#+P`&t<|cn4T5No}k1EB>f5nSMp@metj!X<9sS=Uh4efaLOioOo6-6W9~{4#f(dzOkP2QLE-<=4}J)gB|s=o~N&7r|~zvF>dy&fcbC9Cp&(IY4VDDaM_ z$UR=!%{EVi;g_xCy949M0P{C-G}+WxsZ^VTYIpwVX-$?@%$B=)ER`Bo+~HtZLiuo^ zF%KV1UlAYP;E92@OjHZCCXu9lXtP#N#BK?AspW9(VjwMbT2@8b?)Q!m(ACPHS0~~_ z7A>sUXp}p8ZFiN&+5N_qZtQ;i;n776hiMKbS+^8|SBxbU`x?1Qb4g))L2J&U7(sK3UNGC& ztN)8Jx;m?^o>MmE_VHOtpitYAuTH*5Ng*eM7FG@rRA{ykbboQl-CZhp{peL}VLd_y zUA3Q6D3w!SM4GILW-#5XcG)Jy@i>|%lU?fXy81_}v|$#E(^Y?AZ8(_xkj45+f$;Ov z^&1yEa+Y6RRruPXt^7F$a@Mk`@q}-#KpPIkmpJ7Q*Sy!tr=IEv(yWa+!X9j-=V0ux*=)BRdv$Nb03s|+eiIBq*>oZ z%b3FZK=nrC_o%Vr!ak;joct90orkBY$&Z^ z>Ntor9(~ejIYiYWEgXrkDa8`AU=qieQN!-zjC$Hj-0`YyVP&ixO?khtB~6p6mhI*Wu8Ug$FP2~ufi)qj~sG_eNU^dgEygIY%Hnj?|V7ovB8~EO!4Hc;_UhfXP|6KnMW$WOv)oCZt4c9^WA$iSHLmMfi zc$3@#ycYVu=K)+a`k^7q)a_wNR;>f_^u3ceKI;RBJ*uUwEB2O?A_yOXg#CNqf!D=4 z0;e3AY&8KlUGFgv;ej~Fy4Mmiod1=3bkiR9JR(vH+%pC(sv0=`f7k9F*tL6s`}`Jx zTtH`SJ95j&{P$x1_}T`Jv|Ux@G_3!xrT_1%E1g5g+;QB_{6k6c-?xx*Y5(6#|Npr@ z?Q%Hy%;dEA9}3sgcp}Y{dEt&6${mpj3zW{4^c7XjcA4^rUHPJ$BFi~*ytA*?oI1derT5$vgFGob#Yn6vDD-;-71^vs=n>v5a@T z-ba-j4;*3?^Hdc=pSN^Uoe8>nRZNr(rd-;(1+z|H4_i_D+nCSZLQoB~Ioe!{ALR05 z7$bIZMQepK`im!8j}35>RJgy!&!cdU#)0()I0uSe6t4(P&y8K$TZ)w)rb69$*;1&% zLV<$6PF26{@KGgVPVcA&e;O5CS4xz5>=ihdnv~;|+8leSSYOGD(|dA4!AAHtF`M$c z8g>G<4;Ec@$l20*2G2yQr@+O$OroiBtDunFj>9s?^BonlN!i#6mhGZ+7AKqBHj%bC zX;t#?*dJZ!lw$cHznjgA+@cp{1sTcwKNCgdc#EA1mh~AvDfvvfGROV7O^O?8WT4jE zsm2mtYF3t?`l%~Jz$B^UvsW?@TkU^|QJBwWYM^_%UJa+mLDRr!odDi%&6j8=`JrI( z;HWS=0&D?~FXoHqfBc*)1J6_?+T*Y*&qgD`1jeV&C87zNxR}G_CNag-{{Jv>a{KXu37Oa{#Q2b)szNb2C5BY(KHVGGxS>4cLBo6U6?0Nh)e~b@}FB_Nde&eajxV?{+8Bnxf z5*|C2n6TN5Y=yn|LH^y7zc@g<@yUA)<=O9 zudE8u8$M_DQTwf$Y>B-1JFKQ!7j@<0svd9M`Z@cyk?T^v*?Vc()ZqD*2%DoCafJO= zLoj5tXB#$9)>)*J8~l=_J|4HlT&*~KzSxX#kAg96-@VM79G(auQd?FCogV#E1yr2c0S{=zKPRJL{*6}OW%?rkFJ8$s zD%0Y4u$YrX0W_T{i}s`@*1n0*0dNw2dQcAtEZ1sk3{(96@i&bRnFjW(00W4EuuY<4 zd${iBThSVw3|7+_&eonOjxaU-(z?^!o5JVZ0XKY}PZ-!{zZhWjX}7*<;AUq$49&zx z1Yy{c1}UktAjlf!*>;MfHI6X(GiOOGz8qL9xhUUmlpSkcnVLGP|Ml_xbaxl3s{Ok= zQ|V8x3Mh3Pp$urg#H-i+@;o$Bt#Z?vRrn#5Fc@N6t|zw62ZelVm)3e%;9?q{%pUZVo?rPFBS@0tZO*kp6l$b)rfv3vk$|G$z z3CwU6*_40ynx>1&Z*kx%8Zsx-wbe!n(~fE(6ZKRoIP3WSc8d)8V2*J^($@1XT8>HU zjmWg|vwy@TF{b$XwdF-DYtX}X)iCq7-vDke)7F{pldhse{?3TBQZNxsmNEA{Gscd|@miS~EO;ZLi zte;VeSUi5q+DyIU+6=9p-)d*C z9vXd0!jIk&2MGT*K=^3~W_vH~2okt`xcU)FtsTC!zFPEf_R{;Lc%WS0-_rZFS0fkR z^eAvbOVgT>B6BLoOAnyyt-r-GiTulyqrMy5YyH&)APDI-i#JcB}g*mLJ z|6QSedAo>yhr?}#ywH;^5Vdh3+EG|vp5uy}~p<1&~M;kyk%YBv4+c%O4k()1^Y z{0O#14U7+u>&UVYseOXiPu=KkpXX|oqq8bK3#p=Ev|rMCG6`_&a7@>^*e3h5zPj{V zLMNbMnL*xn8?iY$nuJwGw6VU7XY*&jx%X?LS8v4Wm7rnrZ+M7Y( z*xd=@Mt=L<@~ByAIZNK4O-Cevz-#bl4!(DLvb1f(YgfjFt4{499V*aEvHaGxj6!^4 z{7a8H?jJ6tb^h=hm)BVBEu4g9)uav|G1lHXLRxVvo7Cov!-W;|@7oo^)h26S^D>i# z4~kTWt3S9uQrRg#_{`Vkla=<(T`oLecBv#pZB3ut5hqMViZI50VtAMzY)5AO$>%{x z1AC-b+)w6X4t{6?5cxg!_LqStG{~0Y2J}B_0e7ppi*|U_<{|qt-J>?*jod#JI+D)z zTMqCu!AGIa_Dg!CNV*dl96mDIv|s2cKTx+JBe2Slz=IS<1oB-RU-$a$TV&WbsbHk_ z1*Z7`Q0O!6&OJf~cjg{EHJLS7k5`w&D|%litcBUOr{|GJLVg_1FeWGyl_|4~6~BKm zGUkkOCxQZHx$k_E^Zv5&TvKVZ#+F?cI%G2!MR~Oxz^{6<*QNm@i4kQ8m~yL#*ShEr zCEYZM`pwcldK~86Q+QHTDBvm69x}wF89v8ctCZ~3K1g*1Q@`z;^yBt=4&OMIfrUp{ zm=QYby?`-iqR_dni|egpA>Hn?h=4Y$TJybu?{A9XyqkL_bb53E)}DxkSBLNJ1c34f zK(lD$O|O%4F9+i6jeE`xts)*Bol*J>hrKBvJo4iAjvdIY3#J8F= zQ9;Z*)pBMgq6YFVhIo%k;xf#)ehXxba*mJbfUfhPHOza=O`RI$R|i^4hE3G?@{!nA zRHw9=I@7hQ9zn6Bjud9g6I1tK)kf}$@3JGfsDudyyFGfNH#OA;2h|`>T7iZYyq{=5 z_nSxUvA+Dw{uwilL}vBpm9i0kW8K8r$aJ)^?n8ruVh~S^ym^qISNZ)3dTt@>^B><| zAXGGP2CnlEh$xvYi`w#e(()Dq+UliVOlChm`D@Q77N)j@8G9P*Ya4c z9adU+UNLD9DuuL7?L^Y|m@qho{@AN#nA~lsQ>C>Z+<}&R2;}+I9L)IUzS;$`{YKZ) zq^LA&3`msTy3|F3tW;9a64cBix7O>Wp2}=vUO54VqM~(i*Rt4+th1XJ5H8s(CY6%4 zLRNc6T_exh<(Tgr9d`wKtKA~Q+%F#*EMkK&Z-}N9HXHe*ahXa78H%q zsW+OftceN*eJEn0b%g58XlPaFwKRW$mYcnXWd2fUrjc%Potw72O{)?sCDBUe9H9*& zjK?;Q_eF@-s=70$9sc0-PkG%f866`cWuRt>pFUkRvv`qlZC_@(`cz=?Y3QxnS}Tb- zh_?AF2OU`5$mOrM2g^tO@0TQw9Q`POzUFA+oiEHB-!1{aAv#mWH&=+t^&V-YYNjHF@*?Bt&NZbado z*p*iO5oRSU!&YNl!H`y;!8@?)sIdZ~1aQ|Sxc2&e-1>m6R=*mR@O^EW+%|4STl3>h znb2PZza4;gHlXNnEzoy~m6jC%m3aiJPkMyJ=EV)6m{ z367{%rgA8NFOl`wp?G}8OhH`tv@d-#`yjIPpjfiu<+wpzL8?VU<})iLue%(OOcb0I zdWf!{h9j}(Yx#VzOlu*tKh=`Dy>;7uajaWEx7o-oM@|$kl-?xlKT|v)yw%pO|MMd= zVZ5|iUl;1ede;zuJp`8(9{d>es2_Z2#@7wVsW3|_;2$ua0A2Aq(# zlhxW}w&rIIbHq?Y=Hd(HEOn#PJj4v(EnETHbiGHVh&I%72Y0Mp1peiTQMYHe9CG&V zEl6=FAgmFoaJMp4TRI)f@M0D$WyB?C6Q?ZQW7;h-RGz9xw@Drc={^($GOD$_COly@Kb0J*+B{nRbB9BkxXb+n*)%E*1<{Ln{2k<6?J0(^mg zo;h=GCtyn}(^qg1@W6_W-NvXqS3^u^p|hXe7~d=MFnc!DwM6UPuJMk%KVPO`b{K|x?M6NVZyoQYK!0t~dLK`4 zEomfJ{>D1QRvw)QeWDa`)93cyTf00l)On8BVF1Uy{QgMAlm@ra@8)f}G8v>z!l0VH zen@^d-=lJ?u|4cRo;27X7)CQ^v_Ff!9N8xQ5ZHC_2kr=iLYPj^1%Z?NR z83zoWER!y${J+*D$W)R3L-F41N*Z@)Jxs1x(vhBiQ($ebf(<33BRD=aR#1`yL~OGQ zG?QKm>*W_nW?46U4Swg!g?XBJV`$b?LC$6`dBNX#g~ImdFje0Y&j6Y%>?Ri7SovMq zFGkQ!i@nThmd&f1Ba_Dfv4d==eyR16P|n_%3G!jERB5^>Pp=f2jn#QO)g?(vyIgK@ zq|GVL5@4QI@Ch$|QxtZi#amuz1JjY7lrNB_NVFE`Kb$KyJX9H`utcM)C~IdLCj0nS z5NlC!Wr{N-yK&rBORH|Z<*k+k5Q)JD54t?e@jQw({FJTW+CB$4I(Ic!QWjmFo_~lM zz!-Sec)|yjrG+Ld&1$N;SW9oDp`Zx|Xf7&M%dpH>R~OQbpWE-mtdv(pXh2tJ(|xpF zRw$SXRJpSWU|!)4S3(V%rdS6pE`=M@V!ODA`YTTj=1O^*%#SL+(9a&_yD~Q_q^VDL z?YR~LEwr--5317|qa=pJsW)CA^a)OpqRH|f7G)ASXMJ+7)$3&0Ko*a9a%ED)<&O1i z6CI0WOxWgp^Z8c(r7F{XroL(4mAp{X189RK6T#5jpV3lhw${<6Z_@JWW@@G^s7npP zR)ZI|^Q~H{7clIEeuW6#n$8jedc26}-ly~7=SW$(U|+dTR-;69w=+aWa<>o(1wFHLloE%pami=m6#3hz9=eYnw9}I%K5|GovGBv1P ze-#kkm_(ni4F?uqoaRW#V2|JmrzTks3jOF)LRVx+N)W>3b^^G2<}c-vVF*wj_qBp8 zjFY-Gh$zhCR%P^3RDMf<#>=G>SRkL7U-}79rGm*EgOl7aKc#4;cEg zCnMNxVP`Mf9eb0a`m@`2PPIgx+4@f%`yz*lLu+MA7it)=n4ie~SN|m{@ITsEo%UIV z3GI#gAV)Ose#tJtJt91F-QVu6fc?hinrLt9F5+O5=)Wb`Ot1eLRC^`E6GX>0f=6ia z=lVtFD)WBUvhP-Oe>XVjj`)^<)I-G8rBI3*$Yb4669wF$wZ1bk^!~~N`}5P}@SMR6 z>qZkxt&}xxE3l^jw7XcYc+J~t^K_uPJ~Wj%+J=w^(y7f?fuX3e`mXM)*+Ei?TZ$O5$-e-5AbS=GwEN^X6L~7 zo*4=Jo#EaKTG1k;-xta+v>E^Y0Emh925^b~1liu*&TZ~a+ zO4X3dBxQY_fi0k5{Lz$g(#vtM)EMTD@=<@e&LPc3u&`IEv|;n-uafY{j0H8u+5Q2O zj(v7I+x)N>dLf6D1N9h=1*0c#lx*Dg5=uBP^^%YHcPfj~br*j<& z?QAJ>)%J)E8zxzoh{#o|uM2r97(191^>^)YhI^S42_x`5&B-;2?}#`;Q{Gy3ij?pq z@f~yM#l3vHaMkCp_;yz(B1bl6J~sVPt&F3RQnoY#iPK^DqF$cPk)D#2J=8gra-4-q zD_g^=Lf!GCf-LkCw@S3^Z>0P@XafK43}2FVL2N*!q3`Qz$sVP3%7Y79+EvS^+GLQa zc+g_&d9d)OB0i#-9pJ;u`FWhFHq+<2?Rcj*_ZGA=vHwu4+lPV~o>igxbjkE)@{%sA&hiOM8swss) zb#n6n%_n=ib@u={7C~d{tHOGh4hAALX}1BWl+&BTc`=Z7-)CSq(=2%w+E;Q;F4!!!Tmh!Mcqyj!u)a;xTflR!84W-nl5h zL=cLpH-yi^31s#43SrHQ*O%zv8{u-9Y6yJgZ6qhDqtyQ}-*B(pb&AaypMeU@_Y*bI zW7?nJFcGr#F66DC zB-5W2kTJjUuWL-|`dw#Imr*w*)yHn-;Y-QgGlf@VthMmPji$8wdk=VbbKtE!`#l`~Xh9-t4n^|9p> z^G?}towlhwEge?RnD%D08;D@r+?zYweGMkHEEr{!$d?X1NJ{pR`nrwVbE=S+m#KWH ziU1wBucgSCTmoBVaUnCv!10@iw3NTX79i?&3EHjvZc*t^LqlaMO{Fxt_WH3gtG;2^ zzB9o}t5{Yn4yHOL97qU zi2?hLt=*{4r}Vz&{GT3@Az-+7x(5DnHVvy?;V?-lvZnP&LNqly&Yl9SVP1azn_^iP zA&dYM zwp&L11>EqRN@StlxGTRl)3+CWH()?JC;eTZx`IQumAeSb+TpT&-ECEjjd}gahc5< zWfM6!QX|_L@skJAAKOo@uBy%TJMo%b&rUnsxiQHi3I=A?jyprQ%bsdcz*g_0)pbmJ zDo#hx?O#JaDC|_YvzS;qh8FA~NXrdr^&7cgeV2TT_?3jv43#ZcJY3byT;2phEIi`u zzx~jMTGTWpJ3r};+!#p_|n|xM!bJzK(x$4W^Jnr&&+cz zl-{?3i3usG0{BwjdOH|no|(JKGWbTCs8-)-1P32yJ8jMt@jR(s-5)q>)lk2exH;<9x`=vk271A_WAn*-6_Uj z>?-zY!gZ>{s&0-~E&U9h6Jp4wMV!hhR*CA8{PBL%1Lx*0qY3CE?8|B(YumLq$xjaw zwvMj(kG?PY5s8D%YX$>f-+gR6>l8P+r{USo338 z0`c*CvW8kqTqj`1GAYf!cPpFLfBo7wxakAx*~!?v{LXUhL4zP*1dNp;^E$!H^Z0)# zs^!e2u$|)2&!>E?O31uC}Ggn-U|I`sS z1#+gfo!xXTA6_inAzi2$ln`TS5pQ^luA~lxp3`Az+ zS?kile^T$xe4;OWbTf^KorMfb{#2f`ubqmP;xaz*B!KD;sCoHtVWG&m8leX~TGjg**+k592j##aG#69^8SXAuvK_i1fCq zp-t=f4Kq^lUH>e=8zJ}ZBm;mXIi8NkLnfnei`*5#F@Qg5VY zuB-j=o+w>1Gp415f$~B9+$as{PL*)s)q77HIdt^|)Ir;yc6vLgamSd|*0z0pXsi%2 za$uU6e^z}pG9F&3gX_;`?PXki)Qx$}7xcnc=wb~St zrhp#s;+`AP_g^7y{)O&%urTl+%D3adXTsXuo%ch91CK^r%8P3CUXSEFZ(Cetgxz{I zW$&pe)$TZC1t(LF3X?5Br%wnswY7Rf29AHF z0duUxhz43K`Z(yT#6Fa6F8c;`$`~ko+Cc3eNcUV_YL^tI+yuY%#+9s_Y!N6}JXo@5 z3W=N>!h4VHFEro3b!9ty{@zCh22>mNc6t*e@6r13P);%czcjvQU=Ky0_|eX_SZu$k z-fpKN?PF*dtf}=9t}5P>cpG5(xYhCl&rDNOr33>78`ZcxK=>lM5bOsivF7u>WdF-a zaG<;j{6X{(2m@^Pm0xuCY6}vV%YXa8H;Jh~?<0ly#83f&*0ZUD%*Mj@8oG%gF|QTSG{eTUqUIr9QK(I0ya4{un?0}9G8@_!u>Ul?kC?;Uz1FyzbYJyjcb_Sp6IIm8Av9~45Bl3oW7Z8 zNuZV9L9h{(Ze|+F=h%jQ016e}9|RO)Z?%#!M06?d+OT)7+{o(fea1xNF?UNOx0CZw zh!<;G ze<=3d&02*Yk5cyMhPa}7eZNwAuMf!~UYfqhUd-)N7P(-Yn|pmSN<2Hb6Bl{Ni;HvY z6A;P^Pr@TL>*OR8PpR@n?cdil4fSNy!0LI?5!dU^ba-%WHMGU=*$VIxy);z){b(P_ zPgel?>Ku?L|D+JJf}WDJs&gUN>*=!4_)~UaF*9!m_X0w)1qg!*OWYn8C{p(J(12sB zT*c3`4mFt|oO>~4R~HZOd*-8=>J?hUMbndwk6fw+Sjq=W_zW2e*|f&K9aF zvSlclG7FTQPMWe(W9+f~L)q3cQJc!m3uB-ZbHuT!%c3DSRAKkDD1CQ8%~YXjK5lq( zB%O2Sht@HtoWxm0H_blGm1wFf^D&$#5vISn1y{IGoJ~b}EH8eNiV6p>y%P9>oVz&= zUTPv`9j&fnqAl)Vvdf+LF6D{$UA$w-Ez8!Ww9*khyp zun@I&KUm$5d)>AK5+v|r z_>xTrG#gShyd8t^&l-46%nnw<>I=0`r;|{^-`Ap(@NZX6Wj5jtxp4F8@pls>q$oEDqp(Qs^(%G)SM&)6c z&b8Bf*|-`^@jY(Jerzp*3? z&6Nq(bV2Qc!zkE+!9yASbXQX;k)Bg zbpflqEywnq`CfYhsT|yjf}KGd)D0@XdcI4AVa!Zb%Y5Z)VLgcAFGE_2>26-Fxa~>$ zBrKB=;d{^d@+Esz@sN8~H4G{T@Q=EC)k%w!FRrIWm=DKm_>bK`Y7rtxoB6O|24xjg zZx1RX!x97!=MqKcg5ALcODkhgFF+a`Rlyv$t3J1?rm^uVkzS6}Lb$%8AHw`X5q<8c zPg}}_(LN#pYcg&@dB4yjK=)lWrp0=_~KzEvda;Iq~@F$!y-)>H=n~qDi zSBWk$_?^GqE-=Cv>zqen(6YYnTLu?8DzxYnu9PFY(PkNju=ptYWp^8H^SB?b-lO-P zrR=hlAS?M}D~GSPhI!ehNHoVR^EW1@8Byzp{tbpxGKe4fJZ)X7Ov4mqP-|Jp2CkF* z^Q($^I5(`mGZNOMj9r4+fiA1pE)c-r$J{*WxT6``^?V(Wn0TST-Pe4f+zT_6W0=m1 zee=u9@$+4;AHpPA$X8xJtJWNJ!(y+NhV*~-)4oW9Go~s^_{(o{=x)Y;8kFJRAehij z_Y;lt3oPv;QF-DCjf#m1up~Y4O)xe;Y$^;F{d`ZwsK*bj8Lru-u*l(mX5Mb6@K#WN zPHb`coYVB)JGh&~%pQM`M%`8cZ4AQ}cCmnL9(!r}4m=5{tK1zPf%8S_kg`K?=aV9{ zIQYwSEvxfVcC7MiW-9Gc3RnNqFymkK?@!`JsWNiA$j@H8A5@7{X#>mspfJ8ItwNZU zQTrSlO&D{U=giE4plzPjL$GMxR$(ISux}C5&&9hU$4w09b7_ zfnDrHKhMOHy3~jzX@&gzTTMdxXL8x}z+Zv|H~rWIMVBIXlifid5#i5CA#3_Sb?@32 zQ~Ag{ugxa1Y`dmv7dBeZr#i}uNDnf;Z}qCo5Lnt7HMQP#R)Ggmq@o^K97cQcV_ zZ^o+HDQJ}7*Nv#a{^lWB%ky+7(akmURcTg;<%2&9VZMUbVPHqDgU|d`V&;(y&fMA- zb>Mjt#T+m~80h9u{KdrrB1);O@MTS|_5P z>hHWH9kR&LpYk!VWjDWF-=-z}O7d5iLOR}wjEm-nnU|0Wc|BrBS!%BKhHJDMtakv{Trg2RNRAxYTKM5dP5%8xS)^deg?VvZhKJLz;Q zoWYmiY^Ve*UL*=TgJhT_+lCipm16!=iWw~_`nL&qdag_a*@fw(X@)6 z$R6w9*jR_=RdFqIfp4Vvz&$$}bxmiv_FBrK5+wnfPgx@~?X*YMb4o{B;@PW9%1uIG z`j7t2v2ovhH?E<@K--=t;EC>q16h(Z!H*VK+@X~#W4Y8mGx{|!2RYu)XD z4B2sjs{00x5u9RwbeW@*5_f2A_UfT6w($57p!}O*RBa4#e&okZVWC6xkS8L` z%bk0QnjVV5Q`u2bEzm`9<$r?sJ=-KVRP?Y4#>#1Vvv8-GI%~^>xcsvF*JM3PBh9>1 z1%p!Lm53Xaw?+To!e2!b_Afyh0k+8DH{W-3(z0WmQJ1qMe`rvcFL0@2nAANepHG6O-s!@Cgk0bk^|71K{Qy5$*FN== zJmx)O!9QHM7QwJzhc@y+4AjmTXxZ@L;NT`t%JUOt`H>{hM8^5KG%jw7@8@#6fG7VoqRu2 z?tOy`VO|;JeAl(dV>`2S`!w6GJ~qNAUq|d5a|^EpGKH`4)RdJ|M8%ZF6ko zMbKn*&aH{gF~Htc`?K{O>15aZh%*45MP_kUNh_lS_xjZq+?VQ3mZz?DYqnJVh}nx- z^VA%Nqelz%zVD0U?U~cd-z`hV;1*Wrs{V)4;yXVk41v~V=*-k}`x-i)TTXwy(c+?r z3yxU>@0U+rBYS@6$Q*{%s)zG1lPqD2g>g$`N{ayW!9Q#zXa`R}K_J#_2T<~P+ zF##a;8m<1G(d$pPERF>&Hkdt9;K1v`^g)by-@zN0?X!!olWTh zBhB8dEnOr+z$>95ioE`@nNnIQ7T6i4n9$3?puj{Xw{%8>x*8_Cc6Mbz6xHTd_F|

UCo{vU$hgMa5lscAl{^LGJVn6N)!LHDZP2+_Lslu)-ih_v5b7%QBO_xPvn$zNNo zIxYZPYm2eC-)JBhE_)7VpEU-~xE{wvNbm;R#;jzn?7& zRc;GlF9BPcf5yrbIjjwVH;Mlth+I`qt>Lqpt3O&-ryK42|AJ?s$tPK!De5dsoJm$d z$ZYu^e(#;>YTfF@b|U*Lx_dfC4+_*Wi6n8o&r4Koq9u?)xW6wS(i4l?#SY>MhJVe% z6e~IK+=kE2w=D)XTmKP#Xz%1lhDvjCi!6QKDmJl(uUdHe!2*CvhTOCKz-p1@b5rht zoa1i}?_@Us4SXlvG)pW~wUkZBgS=K%lJ}{n4jCXjtcwt5lWOls!3Wk~+XQ&H zP@xt|-to@Y{)l$%W;pafdTA7*3-9WUol3#{o`M>a8PnQ;R=_l2w*kpg}6J$(#n!GJ) zLampSoGaUp^xG$3khR$_(;)n-;XeGJ}GdW zBNTaN^lG`M56m3TPm3iP%Q7SxkMv)0Qf@E^PTM?V43cDL>~MV2mMM}s)V5(H*@fXB z0*}q?{AP-yJC${N>sw|UNfDhs){JrsOr!na4v2OI@Rn_f=z<&;GZV&6=&UY1hjMn# zMlw>kDP;w#ngMfFDH?;V#=^G-91kgJE_l&6GVzbfvNR`p{uD2)A--E|X#3dfe#~WN z>xm#FPO>)rV_(92dpX~6m4bU@?|B%5Z@~3d-!}NW2B*D?zp8^`_c;@6hqw-5eQ_NpMEbdNYv3cx|LXU(axB=``9`*bDtDfUu@B5x7$*ejDH$c!0`9ZJ?jMd1$O!UM%#YR8baNEc*)@yiXP&4*A9h7+ zBf><3m<{-e@5V=}@*;?L?E4*-?kM&OfSZ7au)+`&>=%j{D_p{~V$GO*zq9TnrTxR2@k4&t+}y*jE=nIX|q zkZX{vLyCXp&%8FLh*-*Nhadbp^4QTP` zt;l(gX!J*v`YMSAN|x3qCbx}MX-=&duRBp>#>Q_#rL>FL51)gyA}K-{=aFF4@fTDv z1mdpE#Kc&SvGe5JB(BOuZM(aN+LT1^)EREYm{Y(BckbU*X=`xIns4%lq=m*wNOagU ztQ*qdQ)=Sa$ms0|qc=iT@NnJ+m(Vlv-fijZJ;Hms^&eb8G|c64O%?oG3bz=X*3@i^ zYLZ0w&RhMlJOm24AGpE*)3+rTcTQi#edDPgf2P{N5qY{=*_8G1J+e3gk7{Ztuwb1r zd0f0Lsf^>XsBdl26FJvkqG0&Ey6&8WlgVxG_ES(GRYx+{1=9$&ehi)`hdle1H~0-* zAD8XFQx|al@-%K)gYiwA4O+Pme*(9QHr}<5J5Mc@;$U4>DIYAAztw5)xoYdGZMg5S z%-myzEniRkhhWqC_1(*yxX?3DpzIjO`sO`*T(x_&hQE0xOw*}!a-q+)6~DsCWm8}8 zyTq>ICjev&!=DB}zj*!B<^8v&6s!KrbMT_gsT|vgTiYg_zKgTI+#eD#<%$>RxwPxEJ^GQ;FJzEqduh1(zMI_8f0Q^;+_$0}u;8YrjH4 zcWT~Bi`4@x_LSDGYfgE;%ryo{=>0-=%`!gFFYE1T{Q}MoggB3O*YIArj~}$pRGIl^ z7YXdc-X&2&vCCl$RvnT>*5D`r^(Cc{f`AN_F{S_TI(nlmUut+o)w%g5O=~kJmvR4< z>y-EQHVl9CRXox_p?|rJZJ{c)jeH((5S4gPZ&q9%I$d-v0{q)pT)u>L9dI4M(^#m0 zH>ay<6y@!^yziJzHBS}Zu3uO8LbjZ9R=4)8kUCW7s~Fz)JHx%*Y9tJ+IjwY#Oso#h zuhp~=w&+YXZm<2;Z96+)VOV;?%>ID-z7Iu!>+-i8`bnq|W?VoPGoZ?#3P+iBkIwy$ zGDNp~emgp5`R{)S?etz{(Qxx1hyAYVD>JHuQfQ}G{62%1b~+~i-H*^0VB&_RBbUK+ z=x$RZRsWY3yQl~~zVYJ-Bqj9;ueHTqhZDoJ9Y5yXi~Jk(Z(&glZo^tOTp~>B&RMIc zl%Fip^;SGCqTd~tNBJk8gNtKQccz1{_`LQpc@@HG7_P?rk73;*Ua3L8Lag4uu_xV! z-MNq3HC_Vl&m;zUI0h-hQ@|hLoDUi>$F%ES4%eH6MCwWU)1$m8^UD_c;(rK+K9rKe zH+?gWVwMb6&t2VYQ}x?n{cH>dGu5xkd$#Y&ZAccf?c|*&&;gl2j^4GjFCT$r$4%ns zQ2z_3Jgbxx0m|DANlV0)%-xph&z|wDpg9Z+69*h5mCSd6h8DY6{6OYtwze!P#lRdNh5~0yoq(Z8!BVKPA5V|JjQ$cO;mNi`{b{tu*`fU4%?9YG=M(eEa%wAlw1;14v32 zqX~w{CsfPwzJl6N9f_{~RH>qC}rWNZ#ZZ?zgZ! z$7OQlmMcJw(fm7d3E&5+D(e>cB9|Q9#dG zHa0xwG9ri)T4AF#(8eBh4=4}SF^8xQsXba&7Zv}5dorzJ{E<9a-@#|NXrK3BE1jMa zk=?dApP(3h=@hZK-(U<7?AqoKHa6~&>Vs;en2rZBh!N0#GvGs`1Gv5iMsmIM$IsTd zDSa7ySyiRKD~M!Y5cmp+|0TSryn6NkfP!8`bO9cg#nC6ZE?jI#b_KvBroW>i`zimUWi@|-pU<79nugpU}|p{wpkY&6L;N6_8&_7 zPTj6&sLZv`&e8ea&Q7r>jZ|o#Y3|SNck5 z-hq^RS_mU&19?ADo!O=Asp!&aTCh+SJqsxTP-O(2JrHv@tJ+JC86QxTpf;#bCKe^R zQQu{Bz(#X_dYa;tf3;QrwopZB=3o?mP3VY%(uq@$=VWpVG%SjG2=`USPfkiyIx;&0KV15Yz73@DRdpKFzmQ#67xCF_MnJ7a^pb7?1<*EzYN$y?w{GFyS z^!}SF=kdL;Sbs93&z3EW74Moe36KFxIn?WSCx>{pw3$yv$~>2o>OI98I5PIPJ^k78 zvP92r)f`I=MKccUY}J-QZ)=CtHyiXcVs-rzm0mdh8_O7M1-B=UTylh<3Dt>q<(ID{ zcSaxlXW*z|FDJ~&br$4>UqN)V=FiEZiI*%X>Pd8$o5SsjvIP=eSKfKq`8!+aibNoV z{7SFtG~`Z+k)7MqtJ8g50tzpkBAVSZB*nG!>dA(NKriN4Ye*~Usl%bv8@ep5uJfl{(O7)q0{oH zBfeV}QPFduC6t0jqThiS>J9uO4UKRTl^fKwPiu;k*j#7YQ-^lvu|EVWF73oZlQ1X5 zTVcubo}14PdxK8e$JVwj1<_P3p!iahFVe14B0&6NU)zS}gk3QuVz!SsPf8;mO!qY4 zHVO+}qrpP7=fZ$abYcn|^cC-WrnQC)qv%OZ=+kZ%9@4TezH7XM5raEcH+4fpHCV5Y z#W_JAY-A0j!cP5jKxt$&Rxsz!s$)|UZROdzj6nZ&eT;*v80ExDF%46+-iyBVEQ^<%ho|IAZ!KP!I@)ShFDFu z^OYT{g|;k3u^wlldIc8R8Gpd;1 zKo*ysVbZ2;syz%tp^{f}X!ABpaoBgrokwK;?-b`WiZK7vN{2n8=q^IywwVjJ7Thn{ zd|2%eeag8urtJjxLPPGSwOerq&Wc(zQCR{f6Buqlv5tNw$l;R9HS#l#JDKZ8FdmXztKqr*3B86WfFVqG^)9`r9!IbJaB zFU{q{hc;YLHcEX^ePP*IZdM^mUE*U+hJ|m5JRVt&S@ymE&DwbVmm>2h@*OR4$vXu1 zqO~XEp|+$_Ub-8cZ@tP=#MbH>O$!u0jHWno?xkOq#71))U336x23ISfJ{?2d8=8+R zR9)|;XO_&D9!bo?dC#_~%4q6sO^@jGcGFI}9j4*M2%gHgt*% zEF}(T{4Lu4P9wqeybKp8;&l;C=5CGt9aqZX{@xM#p{rs3p44{Ds2UVuFs#q)-KW2n9#@#&PhwOkJ@4x>b?C4w`l+zR}Zt<1_7o<*_?GQ%gHZK&W z_))lHD0w>~H8Rcda-W@|tJ$!==x? zEeBHV_7(+`n9Mz8+KzTVNg18*#h%Q}&L zZYoB%Z%$FHB8}S1UVO@jd_NlC@5ZK^cUz-vX#1V4sr`V4>!EsfqHPSZ>15X_=k;Sf zuHdak$%Q);kdKypJ%}6UFX*~j0};80P?YtTOOy-Xp6dZLUvfWgOR9)HqnSo00wdf* zDAV;47=$9{C!*694Pr>w?EU4&{_a%!2&GuCtP2a8=(AfAGI?>n%u_o~OqQ7lU0BZl z&XUINAidVN%c9kQmvAp0dW{lU+%-=-*CCT{Wc}=$Gc2g~CEyB0O;&=rbeHl2V5dB) zZK(xx==*VC*!o%7xuPdbNOQLcd>{M}}fnlwSnemW0 zQAL#ODl|n%c-A&!8oeq?u)ys?~GFCNOT zzZ#JyO(pm~Yex!wHdtSuwsv`N=5N_(l^i~{4ewgmS*nV11RM0DccV)MihPCakph4wIb`+Fe z0*bRxS)p$YUXRz7#L*L^mD?^8C}DU4ezP=7DcoOBtG^M<()*_P;c51@weo;$=p7Bi z^2`!L_^SX}Nuu?2FDt3nd!9~Z|NB$nqE!0sk1k%ecBk^Dq>gdkW{pnitrWzaw<~lP z8RV5nR+=+D6wsR{*OuXI8C7KTApkFxKRXbN#_xKa?PL`N6o&_p{q2E{m zM=Q(qY$0LccK)jtcyue%jT$Mx2rET8>_~C{Aia>CDgk61q?MaJBTM$qkK1Qe0Vh zv5V!r#9UY5TO})pYxT#qiyQc$a`(YjSZpez+V%vxa-e@^bXeaC?G=>sxn zc?001=UEJM0NpOtdwDU)T!Df>bp0c&Qq%FkU?kr{u1?^+@V-X;*r0ZmBZ^6)lGT=p z2o1_ciLtt%_Oh4{oC=SM)Vu$b7A~q*YmQ*IHO(M6C|Aeamh>B+oM_ucWt{eWl@dJuu((x`L`~f^!tlCRyi?y0FT1bC148_lF^B?=eg{0l z{|?Z_`>|fHV_{Ir9mDD8CuUfoHHh?NGj5OZ3Io^#6w- zO7kB=7YbAr)+X@;Urr?k^kAJM!!sl$u%HaPu@3}rJLcDy>X+-S9l!%Y;r}@?YTPmj zgL%S5q`p|!`RAPfAxxwGhj0}Lzvrr0m~X)T)-~eGyMXEGei#}w|1G36U`G55_Sy_p z{XfS7P~e5fiU~Ys5U#4+LVRU>`6zMQC-Jf!5JGtdzibZWlfWy&|FbqW|DW2xs~lkR z|2<)Y{lBfv|F0gD|D#U+%l|KGGl;?0*JSij3|SjCPlf$pXBpF&OIIdML2B=JTGng- zNk?3G~u}iP7U%9?Kb|t@h~(4pTYL0mu_-)e{wd)`p}W`Y~9YN_L_pQ$K(Bpexr& zjUhNr$K=(0QtNPG>vjYbDt{`p8*v{}i1gJpSNr_qmucn_L=Ul{obu6%FEl*Fezgui zd}Dept{h+V(m~2eZB3bE#6xE7$39JMW@QzBR z+oke{8q7-J!FV6iWht2`la;wqdw}urqnZ*SOld3T@5N40a0M_jU(`S?=#tZWa?PJp z)E8Te3PPoORm3o5hn$@nDEpGEn{nCq^|2>OXxR0#m#>9+C?ZPVOTwuft4XBz3^4x&dSpxf0ys>Q47EswoynsCx#%_JKva6P#7H1;~wR%Vu=nI(;boYd*! zAkpx6gXN%lEq{R1)1%LyD8c!~V!>Rp7Q^KL7u;5Zrhtpg*1b(?M!zGa2FMl|98aq- zBxDXrwPKodNoi)#Y>^9$Fqm@Qd*9&(pSp*^{5|hNy8AN48CF8oV%_=g-rzrezrI{0 zjCFT$HSI=*E1nJ4Eka5Zo7rxk80pzY4iR}oCw+q0v(i*1##Vesk*`Xlj7lC4RXSB?%6wx&Rg%eKbv`D$-p!$ zdS70O?>ePFjutX`!q^H{uv~!-4fVkZtT9V-Xzcdp#yE^|^;{2#Ps`vf1aV@4ek|nm z(XzV!N*f>Z6pp9;U*x4Z`q}=;O3SNYgP>a1`CJr8=jFoZUpyj8dPKlwXxs#tL$->R*~xPT9J0G z)=H`wmSJos({YalSU)m>Y;F*sa#FzXSq;iBo2vlYyvhaX$S(i_2-5i$OKFpcrdt83KB(r*H&iAkWJvc9SoDHQcSgd;ikp;{#Q&H0rdl?M>( z5@TF+08g@_+pqbIp+&0;R|>_CD_c7{!d%In7m?2w>_^rRwPWd>*w6A^X0K<& zjijD5aPd%wXKK;mfqz=bPPHjDTkwoTaqjT>sDmUx5^z~9#ONLEZL)MLqS+$l{E;1DsCns67weQskxg`0< zkFI2cI3?aC*vMpqJtmgwB7885(_K0zS|U%C*|>(|gx@fQS3w}>YPO-hRatE~>a~nK zfxn?^Ou)60`Qhv_yy;qUZIUWL`07<`r#U%svNI}3ICq3Hu1dY11QfkSZ`@)kH}r6H z!*`jDe7#YFj#>TjE9sEL_nTVWeL!Vc(WzKWSg-$wdXS)8y&`KtoZJsOw~On=OXDN# zC^OL|z<@*e!xoyTgsn+oUxMwUjkz@Egd@H9!zLWUfPS`{`lp&he3>DFk4xO+eKQjB zGvhWeE3D7dsdOQ@j(_Oq-ydDyqjnEC*uxq;!*(R2_o?YysP;L@KG}|mDr|Gm12`Cx z@+AVI{N2uskh^#`JdafV^ldW4+jFpgSQC>Dv2;XRffc|JVp`QPqF5FfqhDfv55tJ9|xw=WOn3cTvif_f=eCo^vYYW{V8YnJgK~dHskLWUV&~eBGdx0L^SPLE7jgf3;90T`YS*O=wzfJQ)sJ4gppAO)AR;Po-FP-LIMrgo=Y z4lL`(hikam+vXPW94h$tL;>WfrTGZbsOWp6i-ZF3Vw??aAqERTnjyKQA`=F zb)LO|je4by-6ch6_)L{~Q*Ny25G?A5XdG`KUTKY&Ae5p*MG;RgqgLD81Ryp4TPiqy z@n*YrsI>qgBTb$y-vNm+#Oo?_UYte@A4T48VOU!=W7CXG{JvliV+p&yjQw~;{In5f zhjnDQlLz%?C5FR8qBERpoI((8^w#kAO>HXU&vvYu%V{8?rC7f@C>+>|t@#uVIdz6( zGReAkGW|7ecP=Bl-d|6su6qT5I*i0m)}z;AW&T4DJ4=|mTpsr4X@lTze)^MJ5;?|j zU>-*y_$a~kfS|QmziZ8|^)0BwQB5IkzD?iJB|JHHcJWQD@e1})qLzRI##06 zsX2vnNC#x+LK8q%*^WOeMHV?RjjO2)iZQ(%crbL*QwZRD>4`Dv7$G>7Ed)oI)$mqaFpFNn3j=~ImxuC@6#i_oYS&Rcyf@6)vR-Kz) zUTcCgj$M2?PnVfQ7Ytn+sAPHC5?4OD^i2svuGrt{oJ63cVg_3{(6%r+OAkZMSQhoz(EAf z%h%6)OsPG?Hi!2aVwAwTmPA#3W*oAMsVkGA0Fuu9cAbeON4=D~#Qhi@x^;k4KN&13 z)jc)BpBj6RtsHVVPC1!L*&b3FrEf5EW{OvlRN;jZ(e*+1bV;$qx+-O?-??CN!M&Pb z=@p~G(`!G$?+nSjdBkhD=FCWE#ZymHPw)53*H!?-Pt*@Quo;QD+Ix5dJ*`r3OZT^wY3ec!jPF9UM7R7fK`vepMxw@R2z zM+qxsT}Q6<*Pl8{m%No}!EK~C2y#OxhPH!lSb^S(w;MWOz479I#%7K?{kX%3&APWn z*sw_$OKpN}C&}4_+|(lK_bUrA+ic!{d2^S3(G)brhFayh&s-%ZB=(&c#(GK>9@vlC zIVJGySAIxr&l`sZ;8TKb;^Vi7R&GCH+Z|iwsBS`k0{xH|gV|7;TN&qUb6@wPX7cjI z|Fs}RCh88_I`5*H-2_Xaz9{C7ppfBIf(!e^R4-Kqd=wq;tJ=i^wzE8<#XoGlieaCI z!aWKj8jepWq6jP*AhQ8?`&ipDxmj7L39Zj^Og?q(g#>6C3kqKdj6p1-66;uGFwdeZ zA_KzB0`G@xH$^caxH}$^u7V9~M%1W%P6@=LV&gH&dxqv$bk;N{rK7S--q{|7ua+&% ziv)A0%g(7QRRzTq9oM$!0l(p9(~5>^_}+UnH?@6=lr-nNuT;K^hr&@^2-ioy58D@a zY7^y~)SGr4E6n$(n9kZy3^lJg1{5GUyU8gbKXr%uW*yQ+{0k6V0@oNe>;LWXU%+$k zadq>e3$Fa)?>NFc0xWky##`WlL4)`9qffOLCqUi{lkZgn;7xen`Fk&Pv7jlr3=D?) zuju{x!4yN+!-xX$zSZ9f^#zo9jkP5QhVlXFW%dN|x%2j);%AkyQF~=o#Uh7xSpw_K z<&)dOR095%bH6fQTSl0z`R%L`W4M`zvrrBIY5sW@jomn~;e0c0?{fHla!(oVO&R1G zTzdK(<*pU{%iLc7nej9L{UrB3e3V&nYwYL)%c&dHfsX8^wSN(N`wQ`_@M4}d2*l32 z>J$e$6ht|;-8RCpE|!JRmlj{TzpyPdZIAdn#7Evf0T&Dz-|~H3An9)%Lf30QT5IbA zHaee(l9L`8E{D1eZKEMq=U#gtM5$n4W3s5U`%6JbVo zd^Kk<+s5mbG^FDugmp}Oo+WSHtRtb$|4;S0@3SYuEfm-S8-Da~@&)?X2Beez5h8HA z2n<4d4ao9xcxBnb#bt!`EPM?oNaUaXjhL7%0))eoYmGu1L?k}iQqa7pv@RXcFYc_x z)|bFT1%_K*%NM6=HOvA_<_|kl(z8*pwr!`m3JEejyiZ)cJt9GcmRuG7W}p3~yq6=P zK?>1~yb8403OG`XM;nsWRuIK`xf_R{YMk#3yA}^fvMb+@{Ah|`J`yx_X1V#hS2{mu zc_I{szQ-jzQ!m=%S?F-}k+YxeFIChSr>A&hF=GN_AtAeEU=ohB0}Bklx@^;`?Y9qI zQvwd!Q(W*`5vKES-?JT|17Au$U4ip262=>Gle6@T7~$Vb3F6${7(WGptofqHl7T_+*SZLrZaOaG z7JyIXYR7Hj6AsAHQ^oIBtikuOk!sqD`0RMdnp?fp6^17S0?1L!$o-hTItoE@_k1Cs z?Xz+D=yiE2E>4jzR0xhp{zf_C zjx-0;#%W`X3jp|76+Ii`9|@jh2g%PUXPWypkg z4JdS%T8XsJY!HXXsF^IG@xE7 zHGqEAgfuViHhGH6&;l}B09Tbn^IfCp*h6Jr{-*(o(ov&?erR0VsuicT3n#R@2JE@0WLf!2+ z@~%yaPEDd?rmFEnBKK9|isGkN-&0?0clK%3`M=w8!Y7rofD?%Tnt!@kYMYEz+tK## zkl8vW2%d2O2O5?H5fuQFkLohqU9%qxd|~BEhKpZ0+w6~|ca zH3lqCH!`uCgyY!fE(TnFI)jGFdqFSp7)BYSOK@{ghV5@698vS)qq!RP4t4vC{kD2s z2QyOc;Y0IB!3*8QHCwG_DXS{^x)m-5nuL?H;H^gWRHax|+aTJTOa9lglh|Rgvpm+@ z!byny87NXXHN^MDylq~x*}BW@VEY42v+|Kny_If|b^TjzVFJOP&5hVwH}i=oANFi~ z--x9qT{c=EMvhHs6*TRO2Z17a=Xh47r3n5g++v?CR8^wkw6asGd`6(Lk#@un!|q;W zCt(vm-L>kgz2OS_ghkVBGS~I%tvtWQXk~imb8Gy-2^S8r^JG@#GT&j|6r|vfYD2SY z2j$rpFH~~j5AZpLgk2iu)_MGO)}dB2o7*kber$3}71><1=oh#%DbF!PUU<<&Y#~6y zm(DrRJYr%>^7u0uJZ<42xaPMsX+RS*anXb)It4SIzvGLJbmHwNSly9B# zW;rT#q)HD8;#?)3K8jZ&N?!B#s-G5?O#0=dW2VWCU>gxZLL$eR(X*K|94E;{~w>w2R+4`tK?LN zqSH>hXYb<6${YWr!&$qrpN2#(OXW@Z6q#$Lio2aLTK>xRroh%j5wmcrXHBh!6fXgO z!6Ur!PPJW^r0}SizOsnReI(zW=iRKi*~D?v*WfY9gz^>BbXwyToIq8!I8W7V>F#-a zR;{rZNrRP38w>V+`BbV~zy#eCQ~id1lhS$M1<(%kBkEmL*=_-d-8Z2CX^KmA!c~@V zeaLz>t|HU2lQps?ufaJgejdN+!3poCkdou)ATU)5J@DGyolk#+oWGen!Rs?(OOp?J z^5n#yWGz*2b+{&1qqhfjq5L{OxulVelELrzaLf@2kvOqI1&oI12x0e0SJky%r|44z z(YaBx;(_smPd*y0`itMDgO&*OtI*18*!u$;7Dw)m>6F*GBLnZolLRBe78b~{e;r|v z;Kmit<16j%jM*d7)RdafRex2v2}Rh?u_+)uZ~jPjNgk1(7BTo)<{`pjY(Va@oP~TF z`TK?Xl{&z+6^y3;qUvFj!05SAAG6@1KiRj1b|!&T;Kgh3O|Jd>df;;P2+Qo*Bn*{G z5m)tyb{#G=-Fn|i-EsusxvYD6(;|d5!nfd$0>HQZXuGkWjz6~%-c)DxP~J~OK7VNg z#=UxdeYQ`_d3v%7*rIRfpPVlzW)B{o*L0i@KJ8ZDLxBPiO#V1a;L3HQf*=!!Ih8)V zBkiGF&1Wi{l>M>A-jA?OwY41dn^XC7FPvAJ23d*YQ)Q)lX80lH%@xrz`n^5gdnKNp z-AqHiOP;%mO<~&-KdDp=FWpzh1`Jp(yldrN1%Bme_yf~sc)KK^d+&!kh>FSl1=vRb^Nw7-r^MAfS;3JP{x1W?IsN9m1GHx%iu<~ zT-&EOD<%P8tC7AGpXTCGg?)XWso)wEF*ly~#=ev`v(4AhcYgvg{6*DM_&4NZjMS91 z{Zal-?_kjR78Y1ZY~b_dgj6KQ9MAlR&|^Cuadhoi;3xSn1aGt25 zyMemd(#|=u35vZfE-?#Y>%gua-><$rFLX%e_P>Jnx4-L{W{t+6kiE@*#(yS<`0NZn zSoSFsZhgURY)W-vpL>&2k2lJEB#EAARVNt?91|Q%yd$F=>RSF%Rf|`&40xs#$~0jJ z$u!}unDwTsi-D`We+1x2tx~E-rprWwHsb$9OYTkVM7!*7jN)7dumL=0nD|(AH4hdd zf5>`V9`jw|@=ttJr3L3H6B$6$(Qd0*<}P-^3(t38QhR8ZA?xbY`ooL7JE8o$x9T={1t z=)w#gF5U;h-0%nm1jZYwS6lu=sPJ5-t{OC68c5BuaC-DzR6*I%*sY*bPg}nbCH5&d z(r4tKtGh&W>izYc4YA89Xv|$FR!2E#RlFc@>(y~dzKYnj9tl}xICh( z7u`rOzMVZL{;XIRG+m~GQ3-3_G=FNe0+g|oC5BjWLT zx2s*Mk)@F-)W3xmUR(uZ!+xCXU126?fnpz$yH<66q52MvTQ(t7x4ya*e~X`_W@Oy^ zlA2jQ*5x#`HKp_gHJ^9!Jt?#Q97(=7m zF?vwed?t&$;kqw5Fklq|CG3B=5eqIz97x1a{@>5&B}vaYoG*X*@? z9?p0g=T0O~uZ2Aau`s;6e;{Q-YeH?I*Ujf!|Ae^08(No>T>3)m>uCL#6puk zC_#J}X5AO4`|`h;`>#H1$N1G70t*LONu^$kTU48GtCg<#vL@o?EW^Vk5wm^BaQs`U zSQRT>nm<-un2GF^q{=Ob0(J;#KuO)!zp%#{ejwgaWMdY zLWr=?plkivjKAzczp`HTx!+GOP~4aAme8i}%4kG?;%--`vEKh|E41*KulJPFRW8N3 zux_UQ3D!UV%ApAZ1lo}BMcMsm=IN3Maf$q+G~2M_h^{*-t|XcKt6HXO#wJ`aX>ew zb?*Z7ebj?S#^SU7Z#A!;JA}PcMdu+8`*N^|*LdEWLN(!7O^yHEsu9daeY2%eFnZd*6-pAE}S|a_KJLu?bQeK)glz6yWYDhWt|yz*1-2)+G)3443y!< zSgSv0whM{@a<$!cY+<$pQS zA?xQ%b$9@;rz+{jQ?q9Mhyw1*+p;X_^29yxQzV-wtWL6d+dC(msGoF(#{&(Li#lnf zDQLXt5SwjojpSLHKZUHf7jUVrmx;;Y-G7y)1_glN4{$dE;PhF$dQ6?a28 zE=tRpF7_!Ywp`96(j_C!lmy8kuYvOtlYV_#nCVcPfw-Q}gk8Fp*+}o+i9XNlrSIJy zqqv^#&_gm?);`QHZ^Rt&XnF&G)6-pPeTaGP?h zld_M*sK_Q_iSNx zhx!t;SC)voVcKP+6*zQ_CdN)AC@=|w@ytNq(Z+i+DwQ9|Bf6$!l4&7H^NY06crgP|h{AxkV3*^} zX75A%!-3jP#t~)nV;YRr8;DswTDqmrpH-qi&G!#!*wKWwU49zLMNbQylj?*-5~1Le z$lm)o=i{KV&{>P0?f08YjC!H^x~V)D+8^`SL?bl+_9&94J?h1Se&h4Gm6;S8ZX9nC zNwN%`eO_lUi%oJxa>Fky@J!e9W7awP+s3sXQD1V7a%hXA=jBHJ{&4IP4OHm*uJvVr z0(znA-sXC((`#l+ml==xkYe$%XYWi$QU5F#gxw7V9s`W?TaYg!yZVo^>i{ zB-<4JHXEB2Q+MtEk*|wfgac#4kqR<{qnf;L1o1_n-}f{l6-4IhR+LcbDZ3`bZ26Zp ze3E#`?8FvXs(JRyqrX26WPh%|zBm{hyj|IpXZ29St&RKFb5zZDXL;^X2=-(dsx_K+ zj;{&qkv0Axw{5;`#?fOyG6O&&s2B`4*^lmQPwy`BrHrl!a3Wl_(1GWP${}tRrTGQFd6bP8MXpGW z`)m1JeroG5c-iLj<>M235nsKwl>a#D`l-7f2XK~LIR>6Ye0{2B)rByhVX$B+uF~c? z)w3b4N!I!(h))oGjRIV{#}M<_4b69)Q>nQdZ*i65yfdA}-SnjHJk%i}0z zKxStVTbc=fk>LBwK#&Wr;`dvoo);`tn!9;Wxbtvm$*DG(5hGLhqS*LVxgLVZcX}JU zldK>|g{_n<)SBV649)g?*zFe{HNHWOjda-43wU_fsYs&+d7-`eXW+3_QPcVmhFH4@ zf+)Ko=|j#hl5Tyi%xG4rl>Y&=tIwNzljkEmxkRIHtmqjRIJ(*8DNxHMP*m5iPrL59LL}pVt-p{L; zY^8~w3@xuo(zudUSjH`?hFgp)^y?G`mFFBkE83r9YQw^v?>1%PJ4q88SY+s=sf-Z4 z+K9P8kpE5%PM{_Od+2N2MhXF*4SkloMC{)+1W7#ak66`ZG>%IlY-<}F{D%TO(~<~T zMS?EYM6Ko-Dt}C61d&7BL=XUPtySAcCs$%gN*jn0)wx65GWzRqYPK1YwLEYtl}opM z+L%DjzN)6{k|noDNo*Y$kNb_d?tF#)Z$I>(^|knLcXBOZX07|)TH|)o7EQB|Nyp;1 z=l$ODq!mb0DxtoSjNvE^IT10{y;3$5iK05aAu*ALnt+BYBz_ zb_*cBdi-H)?+b=kHgswf{>c+Q_-nf2=i^**`2Lp6l$zp zmuF6$-h4I}rqRdG%=2xO7UwH}C%H?h*X62%LF=H&-7xuml4W zRFJ>jScnU|=g+Bi?epAKq@{jsQA$s1hHrQ#%4^hH+bw^KH-8(1Q@qxTsoXRAfjWX} zW8>;U;}ESkgY4ix0G2R8q26J=boHN|n9b=)R32p%S*aj? zax0fQUq3-TZ?pa|wyra2lf26xLuaDI$FEDc)f|a-<9A14)gb8Ag{Z;M|BANJP|7@0 zOmsS>eC_f~GB4}qPP?bAE4tWK5I!H)8AvW>l!sk9AoawMt#QYOJSywt`Xz7!X z?Q^@g(UK4J4Z7Djl7lmk$)KH+c2EE%*(y?!`K;!sa~O5DogaA0eL$pFEBgJ-uKd41 zb=I1MzkHFdC?w9w7C}7KA*a?9s~Ruc;&j5=AwejbNbX2Z^td? z+wsk?OY}D3yNj+Z727SedQ7{o)xKu`0Y1%7Zd&s9!}Ip`8iTZpW^dw2WsrbaSPPLZ z;m4f$xrtuxkiuQtu`_*U1}#fg#zoRG&Uq8QvkqWP&dF54xeEh~E_AYLOz-K4+T# z)-iWxR_5&%{;vMr?0!0L+F3d;=2KhbW()_uqc83E8~V0Sb$6ZHqn`$*pTKU0rUPU~ zpG555{Zuc#?FUinFZsD{F~p$vsn4zI`g8>RDmDoV+c(h(-uv9!NdK(YPIFXB;H>v< z=j8MUrIvt%UBBfs6TF@^x35C`Q6WgKmYhb^4s35giyisG6SYRXtREB0bse!^wQ4I5nTHG^U}z*xX30xODJ(c z;0G9qrU`~!Wh~2$_$-1qwcI5@OBYjYU!>;B$5&Oh#-nV11T;O$lL*z3ne(RF@h>7_ zxI{kY*dh9#?-V!Xi8K(jiOJRxNxzqm;rkyqqTcmkJjpv4B5;ZcZ1!gD`hJ8AAI_v{ zP#9UWuewU-7%oWBQoS8Bp#F>LT7`zkD6ry2@Xx_*Sjz;kM))59`g#0iSlZL5WT2?j z)2=nZ9F*(6vbV-$-CRBY?X5b0MBS;hL`R+;H4W8$O!a`qsJn&RnJz~FY4}Osij_jf z?Wj~6+Z;|f>j4_@vXAROK-Kgf~PhV+O_kKg)UBqoiTIJ2n zU>GRUgI?&P@5Z&0zFJlt3XlYGAYV8+65^EMILr1)66F&SLu5XW4SJ&Kj?kZTK8?f$ zPw|;!*-+u;kj}x5C7M2e1bNRvW3JRk z+V!_#^J~p^25IFfNm(oIBh(kQ@ah% z34uC}@A=N8QR*yoJesY0O&sgnm~u{bn|*ox*F`KUs=jZe@^Cgp~H z@W4H_$AnvbC6}Wte2(`|b&Ssab49py%ne*7{y}HWjaPP>7)uciziM#v>zL*aE_nMu zq*bqr?MVwM6Y#65)4i1$IaNt9O3F`Z#;zhFiOK-2UZVVpyC)Z#`eHpR8&gIpa z-f*c@h0(JQoIq5KU` z&XsF#bScMy39Tk(!iFl^P2@7B=eT%Ac)o%A^Mgpl_o{ zVzj9{i%LjqP`fIMgEi`dK`qLwt%bZ0EItv-O^2Q)>-|t(Y<{zsdxE9;j3?ybz^@u*-$uR?&s+{)o zFdewaG=G$6l!9u|l&U>vCz;H|&75~`GQ^=kL{s+&OxaOJzo6k#W;k%^ufQj)Fk`5; zs|-_aR9`09LO&&`K-Bq_TiuT3CF0>1+)=M#7wKTz^FvoA?{Oi@r&k((?|yMz*DoLJ zia-@|J-7)=eg?`9f><0xC(s&S2esj9BZ=J7cx;7nu*}@?soh~zaE<~gFepeEO~?3_ zHhHT4&I8}r=F8r!A;W$0Qn1=@2nB~TCBXaRi<)GM2yGj+owO*1cR&HP&-`%Yqv zmB*P!DO++L{^yhru#P!t@tP#jFkc_pTHDP?9_gi&%FaQ+iyG?aO|~ii>Qc991T-gN z4{haLwMm}7BDY4Q=hSBdI0xmLh~rv*`f1-`yz(TjkJ$lydpC?*sRMVhm^WrYLE6tS znz3_9P*p>luJvloxRi@LN^|GcgKDCI;gpu^dbbt6|L+by%GQH2(`&pP9qbWNCv$j7 zXP@gEVqhc_*paqZc@BLGjRf*#UDpU$>OeZ)(@G>CYfwGPdfXqhc&jnhpaY9Y-ms2g ztvaQx31aQ>uC-uo#`Vyr$KhSvqID22Q{cMJx>2l-L}1XS*b;Ao$ZyNjPTT0*emh4a z=W)XT-H%29+*e~9s_ZY+M|@S^%Dvo%X~?ZXOc_vFB1Xzg#OX$cpC}(}z&Tluav#^1 zkwn68uAK#!I8zOxG_-xEFW-MvUe!i_l$@7~bUwJ(Yv95wa~}8Cv?TszAO9>z_;&h)*Jqum3Zg#!?fKkwdH$V`!THt>`3mpoTB4-%RmO_ zv4_GpqpM6Ca@nzL^J0j$!onrv0Dl*lds)HZ_x`Cp(yMvpE`GI9*3JTAbyPKJL`4ov z27`hm4FreZd-W^EWK@1GV&>H|ssD3)5`&kY5*Krq9H2kG`@Gi_eH&rS`fk8lB%s+^ z;l*%}u16w|S^=%j{yR*uL8G^KL>3Jpt>dgOZyvI!D;Vv4`T%>uHHpNu?^BJ+1X#T| zvwpL1SlF-esn+gk^E?z09tk_CVRe{7Q>6b!>$Q37`>uP=1y(Rw?y^|lwzx}H` z<_dAq2vewuIdeiAGFigvOXE$_MkU;Wj~IHJuwF# z^12Fnx8*?B!(M>q4^MkawT_#sI^N3WQnR#_oZ0y^-f9tT9CJ@3t_1ZFC0Hl<(zTjI zZZtC)TMu?##eb%s%;N-icI^~h{sWL6JNe)(ju_R)5vgBzmRd55lnDI>btlg@N(t9` z?c9}1**ASmP=o|~#y$ay_}EXZct%B>vDi-EFS`Rq>X5Og{f>0(T1O)2=ihVIQ?cDZ zX0vn)h&OQjmxD9x?OGc3Sz)!yi1jhoQ>4M9D7}`9Gh5QOCDFt+gPK}1<73hXXiOAZ zL&=QsJP**_9&r#Dl?#oVyj;DFOt&sKT_F*>^ zMBs!^id?&x3L6S;ry!;a>>za{n4#R8?=HA=ngXsJ!$;WMgm)W{-A!|zl?GOh*r` zE?r9R8vRrYYR-5Q5B0W6yhFj)L1nNp8c110;P6St)2a2-m8FhimG(0Aa$oQnxW2OA zagb;9iF+b%f}1%~`$@?1q4V)uEN9wepTZCC61)Co%7k9G6#W#Bdu2FnTt*5^;$9<{ zj%4sha5u2`+ALBcox?4;XbL%x3ZHLCZk-;+c?0D12@-k+6*DagPQR=+a~#;rt~MEMN}%TSgbVzF8l}#@gLFb#QVS zcdL4W1@p=+-UT==M>z9bm3M=1x=UH$w_ie8Oail$Xt$xf64-MsXZ@hpJgpyY+@1J= z+Eeds!ZhC+NBT4!%>be6OuZ`IGid^CI?F19pO2?fBByt=Yx<0WV7%my#g?%w(5-?+N)EW_`Voee=Bsv zn;4lkJ-*-N4YUV_vf!~DAa%8nfK~#t3>B8V@yO3#SmAG%bBiEz?FGUI=!XI z`_$NMp4CG>_!{mM50;_SvaK0ToSCalnEy&0b8jg$_FvTT)fWLLy9@bJp>%hI^2rPB zlk~(B!OxQ$GASayOb^}(1)o(IC_F|#a!cBJ^tzWzFkNxK*4fLg~E!^^9P-%*ZJ!u)UZ`e(z*1s~BFlX;Czo)p~EmTU- zDi-j@uzvC3dVP9xF?QiY|4*j_LufsdGNI$HxMylzSB#=(ghqW3N9sM!by=d?EKnit zxC2ZpX-@-Cz_Qb)X|4~%L9Oj36uA5$h%GBisGWfl(j%KICk@}-lB`|NOHq!+t7Ln% zdX@oQk9yFWTH>&L!x8X$*N(T^ez6!+5w$l*Q>v~}@?C_A{X>Qil<>SVdFuYAZo~ux z6T!~K4X@noYh9lIrrA5dC$`;%RA-7k)%B+Mifc0weqAxDw6L zzp3R7^b%j%r2RdpqPSz6@tgP=8rE1+V!zmprw0bD0i<}XRR(BpJIgeXgo3GunHd^+ zp@jBLLPh*FT4cC-Qs?D@EV4(Y!7;)xXR^$v>P?%~xHG*yL7|~9hp>OYtR~yic(*0< z0CgQ^@$`L4D9h3@L>@)ubzx zbyxQBm)hO2C@`Hyup1qkp8s)5r*>&~Y;HUMS4z%GQ9-Fgu+mLJaWKB=QkP(Y+x&He zI9l{F@##_t>$!95(_D*h{5Zz=M`+IjtX`pH0cLs;!m>_}9&E$-``ZT2vugT_e} zxY74oe@J9hm-AS4@3Vq%OLKje0auk~1i@!1r=5|VD((7|nT@eX&9~ zQyERLK(Y;2!jB1$RE@~ByW#%-0F*W+Rp+z*=K7SZp=>Dl1IWzqvtriXksfvc$h3kz zD1TdLZ;r?8er+|i3e)kj-V^Fnt~6_7T{DVgOECVd^E0xp=;Hm1QimqHsMfX7{=0E+ z_2fcIv>PvCuD%g%($j#~E*O(O3PEI|{t zB-B;=xD)-t(z`5H<%QP3;nJp`OkcfEg@7-uj%_sZ3J*GRt!&3&+Mn*7ji{i$M)#$| zp9lgYW|cVb$gTH#1VMTs_VQK|^*E;#h7dT9*;Vo`5s5^vYv#=$7~Ru*+f+p(9aF1MAxI~tMA%;w)&Zk~ugmzhqFI0_iYs#~#n*K(wqKJOU0 z@2c$&I=0zL1f0|Vtt+T5NzF%dquOr2EN}KkcWdfx!M3(`6zt{qTK?wyvBgMux6NYu z1^YlQkEgfv2_8Z&h1p=ztI&>F>-G9(Bjp@3q?DLVwc;e~ih;=ngWfu@ze~AQesSH? zx+-InuVF*- z+LOn7ACu%#H$4uLz3(zu^63+$bco2^Mx%=r=YOEAy;Oq?$@3q31!7z<%WAM4ApOyW zTdS|Pm71ipmg9L{H)?ii|35&Tlz(YKl+34khcC^VeI3u}WdbGN*fuj~_GD!k zEj$|$U$MA)6gM+)7DMT#joyS{zw3!bE^o3Yq8}K7bCE(+IDIdK-s$yOm?(8i%+%h=4~M1qFy&ueR`)+%ukYm z^=OXugmRZOQBOgKLs)uzny_n~aut{vf+(AXD{(jHrt`4wNC$CtICs*N+U&OzaF6QG zP3B;m@Jzww+$)<2uGg~9-*<6I{ViRsY5oeKe02$&Ymm3R5jcleeu@=ZXc_s486xrS zf-W$iHi5SlJ2yM6Z%!@Y>Db*lvL~@ZPZ9t7uUavdDYG3lVWeGAvwF5RGZ;77sAAid3$XH6cUD$HRgNnTsG-BEapmHPBh?KiqUBqQ(}3GF;eiKi5T zJ=j@pnDzDMRR`>!?$G($I6F{xdcqA_cY81qR52v8xw$@;FNn7f5v^#Y5#{N0jt{4# zZip3v2-i1oR)1?4q!CVLoPgEY*G}%5@;_8{=Vh=v?opUdo%Q4Dj+SHCh7w0<4Vu|1 zqgh;}xpp*tzl~v99Q=r>5lF?~U+RS~jAHM>B~M!|TL{-|Txna}YVg}M%CaD0^}Hn_ z+;?T6tJ*N*Iho3tv8n;@CR~ydyUPq^I|#$iHX;M^1WLCWB8?4_ILRPaXas()=TTE@ z=AAPngvzQMz{3R>D~*P-k{2y&UJc)Y5~Yy_{!@%+X3A+`1%ukoZ%(Px=)pE1$_tda55g#Z0EsgKT7m=foy5Qpr9P&Ui3aG!{ zdN_;vSx<7ppe-+5LM#tWDvDpPNp~LY4?>Q}Du zX@4b7U7Z{>F+T*Q91ro%fg8^@`MiF7I4OGI znLqzpD9wq+@`_D|Xi{Nq)B^8pQeUH;TKKML@Wc!ZpI<8?3g2mux|OhhL$pGe#Bz&5 zVYgdhy8P-fQhd#if;bWlE2TsK|h|V%n5T<@^@+#QKnJ%R=lH!-Cl#MS+1g;{1 zHi4*F!%S0@ebeetCI4P#9>xd*%SNmnQgbW+9z|B{E*;e8!)Sbw8j|t~S-+cVx3+3= z-4#DN)TXh+IVX(oO?CUszbeH|o4s%K_=G)HNC_ulDw#*qpY1}^zz()F? zG9(ZZ^wv3pe1DC#B{WgS_Wfe7yEE!PtJp8GKZxI~YbQf7IR+234L;KL|8`PmzD-SaE*tLo4^Vv; z;mMeHC$4iM+_J_(bI?aOA<~G&RdH^%Z6!xe~|}I>JSU3_tmv%oR9ZXV$6Sb7$~gNG#5i&_$6vnR143Rm_QjYe|A(&X?X!wP6Ee9GuAp^%I zvHE<x+5vO6ldgm(m#vxrBfg>CxJ%B|6@q)6E796j zDWuGN@AyK**6!L{9{OXD1i<3{qNcvRwvSSAB|*a7|rz|&9V9Gscsf~_OFoVMVC zIBP5q^{%yKt;PRjL>WEB-uRV&7kNT9Ro^8ezw-Dm)c&wLY5FHB*nfb~vV_<<9~%(t z9_Kk*u3EI4y(S{6^#EnJ&HavI+lS~byk8ztdU&y>`5Yx9To;LNi|I@5D=TE<$OZnH-Kj=i4K9*;V@;{`}&7G#q- zh5ci1w!Vd+g`^j1$DfW5JJ$K=9Um7&f&{1AO_PLm%Du;uqpC$t8`A0KSoKerZnc`D zj!C|oS#}hCiP*Vtkw8AYDxFKju|2AnKm0C481eMQbi?fc)R>61Nva_iSYjCUP9 zEA|i(;aM1*M_VYxH~buZo%4@Hi`>(HXM1A4QR$T={{P+3hHet6-EJOAG3k7 z#aO)qtUEffXtkD*-J74J(g4xxatbRD~hKbOrr9VhC??6_MG z6+@cRJ-pX`HnG%nbSv#R*rJ{@Cm= z4OAsGWw+5nXc@1WP2xkUa}H^NgdgGcb*{f6;6Ff-D$0yn&~NP94L@pd?#r7Zu zx_F5Rbo(r@MC1#ui5YY~?;n(s^W$Z~wi%`1pCns5@jSY4fGYWKFG~UG1J(P8g`8%% znJet4h~HLLirnM(%nX`COUvWU-%rbua@xV!226f8 z<6Ao|>2VmR$%=IUC$QsMeMS#d8J3}3V^FdWD*bub6dcS0$tKcBwjSz3M&S`@`7@51 zv*GciU{5A78Q#gX%}Zx)OWNcBn<~4UE-|B{2!!^zW^GR_!_s1_%V(7Htt7(Stgn?U zqX zorfG6C08)IB>0+|Pz6c_0NaXm3P}zQmpd!e+IwlkdxC&Asi&gsk@uFIkaO-ur7+H$ z;YO`1r+1rF=+d2^+(9typ16*5>xc=F-maQpp{xOsCcIRqvXnv1`A4Y>vNv`IY4TSA(TV{wh4MB3TVBmWFngIhflcn_imModPayIh<8rhTpLmo%~=&YKkKkDQHjRlQZ5QAC(=bu!{U0FnzMnwfx$vU+;2|!_b{Etb1o2ri zB?kKD@?L=9O$|ZpXKYjbApPHYGIVXUlAjizd##Kv3V&5pip#BmS+Waa8Vtt69%;7m z9%&_1HD_pl+{fIksi`85ehRUQ_BiIp39=7yq%ZEspu^|Hk1d>(`4)S?NVTNhW5rs09S`hZc{gxELAM_ zw~?aP@1DV@xgKz!>Qc@i`8=jOIvslURUyrs?LYaL1-c^WeG2SIDKGJLWaf?HywhL5 z`{^7E8%;gEZyVV6#txq$&Mu^JvXkE?$2otGyvCVH>YC}YEF`Yth7lhQ^!PnhYn2w6 zpL1O7xVrDhlNWzDjwb#*6-9=-y>EGDaF%Oq?# zWVk+jK?di61!elo$W!c%a-oP;Xa8JDpKZQM(`I(WWkOe2sEVR7|6J_4L}Mj_;@Fs( z#ayWH`%CTmono)D*2?n8Mh`*T9kTIiK2)q!GPh!prC!DCG$!VLF1J0h7DEUWPCA%P(A>YPi6>L2tr88iZrG@wSFeMRATZW*ks{9N%;G*me0%K z+(?ViAvwwi-H2Ds{AJtS`kz}p3g*NQ(>@5<&$U2n1iW?}m-5x*9Y&cc^MpTbwFfy2 zdTqW(+FnnH>+YRGVM$c_>r_YmPMtU9;&<+d#BO~~)v87mi8=pYr8ag&C;Jih8JU22 zvW+ubWb)dqg;Q{Qm`U+7WA z8bLMBhKmWA&3-och2vH+_Xq>(yUgY7{=T#0W<#B>bTXserfuVr{9Td$k#6%Fl5(br zc5?%=JIBtdJMCeWAGtEG>eY-XjV)H~Rzv@J^IZ8Hmz!;Fo_p<18{=8n+O021&Y*$! z{hwEyM0e{8{fgrm=h90L$eh~M9i~S=BT!{EHO*spGg9=3MurhK#UH{28ls5bOKrbe z=I;l*I(Q+tWC(i_a~F=FiKGg#PdGD>cvAXMUoBN7^-8FbWV_%+?V>!w6n?OxvmzzL zEB3agllB@cC91Bz@0bkF3T4yZgD~t4qbNh5CkZ*lw2mai={l~m+qOSr*wEkX2`6@p z?^?(ivCzKy_~*ertoDjLs(*}8>Ly&|vdddEih8jb{Nc~NZe+`YMzx#4ma?|H37Zk* z-MQL*dE^O?hX*y*pq#6)wU#SzLj5_YjiED4E9^gj2R{m;oU@HUbst*8!I@J(@#w%F z_Jd4|JiC<IQFh%)q#uq zknpSd*FukujoTzgant)N9&@}g+g?0YMs|8Be?M?NXqarS17$wk2EyrLWZhN#Dm#fg z(P~vqnCy3wcVT7^T*;c|ss%?sZW&gcuXWzkYnw%!NUnt!coi<}N@L@GQ#4b^KI9Z( zCOzuBwZ4oA5&`U%T6({lto4#-m^=dq)sA+?YJOODVTiVmsXpZ2%N3p9`cSwLsmJm{ z1p%3ddyk)Z(Bm@uowhT-5DQO72(+{ktZVnufNG&N{X{VtRlYSmm$fOwalyqKkht6DVt zs<=?zon6+Ew7uJRPQK33M)v>wGJ4J0nktUIJqA!y`ini(Qmo(FsuQXz9+U8ofMnod zzTj^Dnc|;m+%8qB$6l!$ymiZYnxds+j7&t}Og6y1)@*3c=};y7N8|_$$1PNii^Tyf z0HA09JToz)6v~+<;(oo55{OKRZV&v*PCdIO^As(V2PP??LtxEJ4qHRp#9;{rAXaD* zBMst7XV->Fu=M(~8%!xpA0LHt`wp8{6&@`O59KsCZFKI8jQ`Rn=zPeGJsPhsJ@Wm8 zcp>sc=i$SjWWD%#*J|-tUfECEwiK3Rdi$z7r1(<`E*1Wc}cHYtL$i~LJ$pX zZ(s4GgpnoZZLJ*-)KyM94J%d|=;r0VsWQ=F4S5b3bs^FwsJ#x1zp1RwDZrKUYPkG* z`audrx{0+Kla`xI$1(8E54fiOawEc=Ti>1`T@`v}BRY<0E?k&pD1-K#yklP%Y*eJPbG%3p$RZStc1$JC6E#d7N|=15+Q zg|)@yBlzpYnjtGq&7+JYG3Ifv5(yZK+&4%U>ObmrBcmNrVSxjYvC(&x%IbXtyS}Yi ziS3Y@uNxLj^vhM+RQSNjHQmO1l_GZT9lAmBj!Yg~F=&eJtF$CpT4k)vspZz0FX(M8 zHicW(yh>A@o3MxpRk}y0#(PGzkZBP`@&}FCmoEqwSlpW|^!VpvU?N3usplTfmXUS| zL?vNrwJbGr1-sn)!NM$Pl+wQ`oxl`k`iJ@8pw4yXl{@29NEK+M_&y$NMb|o z(kSe{9;wxildgp~2F5F`a`C}2gcLaDlXrR29OlS$7NPFzhvKwjIbaK|j47RG`^!cc7)f4gzOHhahP|{U0MYl@z*L3v`I6I;x ztsOtHrMtd1**>k$9M>L-?lAy2q>9xG5=Ir@x-}iiP6nkR)ra%b zb?l`vZHdDcBVdC3uPqWDlBebRXn8WiSd!e~9G_L>G5Y%~t6b02KDNz`;!QyG&%WbK zski7qR%SLdE#MsMVEno1)l};=@1qY5$V%UZn~M7Yn#aLjhgNLyNl!3JUvLCr=tle-f?1#T@xRzNa_;aQ5X@rn$$NCf?Lv4F7e-A|V!W zXxH_wJtUQa-TYZ)>spcIJ&T4#7apROtLPD1Om)qw5si;JgEN)!Ij&6PQYLS_fNO@3 zL~Yw1_P06~b944Xi4}qAT*F|h&Hg%!CkN)iC!KT3u49>9t?!+KJ#`09qfXu*A#LxU z)SJ&sPu~WXR(LQPgQ%;4@h?7%5ASZ}Rl078)DcpeJu0jb@J2ge1CjJy7g{*aPupE~;FIJTXo ziPw{<*vN2G3lGu|X~FnKj3^Dq+HcklTnH!Y-b7gC8?-kqYP2*%khNN6$0!3$+PoCG*qijnRQt#t!9JLuv zD)Yuk$)3^FtBC*IGYi6ce$IR3yiC1d%)P^~p$SZVEjnp~z`NTB`)AvRV$OG7Q?*Q{ z?(LH2+1?%2ow5OsBZ8yOZ1M%MJt0xStlL{_OCP1^ zqOZtZD2}#)crO#_LI|n9^U9XHNDM>%arN-QWfga<%#d0DpYrIUDwn3-{ZxGR9NHD2r zV`ql|U<1~jza93t)z!6Y@WwpctxqVYDtu&(D-OvfE@K`Vzjz?lt|*q#Y75qvOfs~0 z6KsHvCxK0Gg)MvdE+B6;PyWip11Mdo1T1Rl;&w$r!jiWAY zqRkqu@IE&}^KI)qXD6oue!qa;hzj{}!@|nvt)-+#R+noa&@X<5KcK z>9KV}EzkD(47ZbTQS+%NcO9j&4^?85Y*a`!*3u)C-i;m*b7RH*hH@>djyr<_Y|Rpx zFVI|1o5k8~2J*Ygw@h?#o%@l(h?RR8O^F`;y02ELEq`>3?VajTXI?uBGSajt8nd;k zCA`jI)Rds%ibe(l4TlY;I}_nlmz{K+^q!Lu3C-IYTz+fJER9fV^XV7^?<3f((y-Ihn` zegQR3da6K^%>q2t@>ce>TYLI(I?0P%WF71;_{FiUk`do#K$DBqh9>%%&1xx-z?D~e z8Vr$12Uq)#(%|lPt22q`Y%_F63cQrz|5O=(wBFNTc2wZ=eWy{MU;?Ilf4%-7i3?Q z&0GqX8FR_hh1Po3p7ZtAwSBsKEj;w}l{*hy69EzqopXI{N}l#VuS zEnU@exn?u$y>gBG zq-H&Fy8Y4xUo&^X{|)>N)F6KRyW#&sf^_s#$GzXdfw=UT^YT>xx<2J|rZ>UrQTzKR zad!5ST4|eW(^x&zQ?lA=D#)aN2+b=s1qnOwczc~`VXnTX&^fIJQ5)r~ zrxErNsMhw0qeg3>#K#GRI?%LV84Y?qc=8+0NJHDe&-6t!!FG%D>|82}LZZ?!y{kIa z3I@i|Sdv)NzyoW0KklIL4XJQ3Ml!+yR)>CF)+uF=>hb9lD!+<444*nFI#>RpX7nP zvUm_lYY%v$F#Hd2knB8#j3?DE2?vG7ifd-1*j;Zc_Na~Pz*`)0;44ScrX+qo#ddz`M&eMXsh`Es!2 z8u|3ebdBZQHOy1ZXwxH-ujk=@P?Z@8HT-&p zx9P;+8aqVqa?I{S0QN`H#JrASKb=9?RFLb7O&JV4hZg5@wNR~?Dfvov3dQ?T2hay@ zop4rBxpf9d#jYR3vV(TGwDcTLntg7$@iM?yKREem&FHgh z5^|#{dK?tUmn;@3DtpsY7T6TLQi?(0U_vHkbd?+3v(P ziVOY&Y_d;c$40|jgM)%2bK>Dtr)lv+>a~;;wodM))%J;2e)$VacoUm>+pI zk1LgJBc=BEFB;pTbLNGyEOXlc%MwSR_V*|QJ0JuVuC7bOys%BM38W|&mfMar)k%|j z)?Xwhc1dMh{p$o0TWYLmP%k9O>Sr(N=h+V~Osv=8AWX#a<48 zcvX$aFAby@%x~-8MLF%Stv0%E$D#Yr(>gwA?9CrfzRllU$LV#o_Fjyjm=wY)0g*mD zb}ns0ys_r3Y@9v9XJ?7y@W5~?GxH*_F;kA-(B>X zAo$iGQ*R+yl4Z+X%K6Lu7R;~K;Jv}x>Vl@lj}RNWN@uO_?x^vE>VPlA!cO!pL^rPU zHays&)|iP^3gP*KfkrXDMz7m4L5%%JTHD#`JTxcX^fA-F69lHchb^o7oq>xQ9k4?4 z`3I4>JHs>i`t+IM99sL7KPCY^gP)mPG0ATP0GCt6kc_IixWD>tyw)^5$-AkZ0y$}z zA?Y+XkKgx<`^|K3^=ePTxaR%k?SqK73HH+V#?y(PBe}6LElAa7^cm*M+N-VEYwl?N zbO7p_l*@vxzE+Y97|M+6MlmmX1KsGyH`jmH*kWla+S{AuF0j&2Pa$UWy zuQytm3f}hrO39k_GMN5;qJ;|ql&FtWvQ#7=xiqMW3Owmtt)=P$6y>f&oC+9?%D6tV zo4?;^M>S7Ys4U*sSi@d%DzzDsewoXiw@SGPBy)T0ww)$8-Z1`Aql6Zeu_z%{Gv#ET z>*lXJIBRZ+PIim}a(R>6!VkYw zSpTJ^zEoPES8Pp#t<2P|-zgZ9Oc8KZsu&!vvXH*stB_M-+4*v(1ClA-6CpA^=QX&&@n5$tdj=v?~Z z>Bpwj{5(j$kz0Qf@w~DO*M`gmO!mjSo-j85)M9GC>m{O*y{#dU0 z8vQJYP}mbv*pWUa!JXmKq&=EahC!u?p~~v;!s?J6t@O< zOQFTBI0cHkdvJ%~F2yCdCTOsHlYi!UX69z@<|Y>>$<8@v?;~&aUTX=1>K*L9b5*^( z2{Tl$pgQd8`ThBIF5Qiuzdj`W6~`Qj$>+9A0LjD2?|{$m!^n zgT5B8MvG|+gcL7v&Di!1rF&K4O2uaKi#RU5l%XlZXFbKGVt)EdfyJxqWhX|?*`Ghx zu2kIf6=*CR_vh(xFNKJJ8!f;OeAzWMboyqX3+ZCey z`AA-goVwok$jGbt^Wt&@NBj=++}D1cQ*FM-A~tYDFCkIrHI*Ut;=8CK zHlVwhJg$|blj%IqIraW7WAnbW@oV$0t_{^lx*USLh_Tt~B1fCG0ZV2#l~ieM-E#@^ zUpUToiQil~`i&XKFHiAy@jlk?w;6rvt}H2i3>ZLsils*;#dCg9aSG;%8}u1 zcTzZe;(l23(x-1Ru;8pRe(hf2iQ|wy49W1)AjO!MQy^QwjK;@NFHAC9t$2X~?Yt(p zi|n{>hf$?rnD!HzB}N9!H96(awJ7_HgVIeWq)T}u#Un=ciY)>W!>bFj%%9WJn8}a_ETp|^gtI=uo9Vb z3HEP{;FRA$(f`nbMGj023!gr~gTSS@;wCR1C$SwH>qx#l)NK*?J;?TK;5Q(Iw#Cj^ z{;(|8{8RGecPqzUk5zYh6V!BW^RJx0zl}FBxo9=-@<}py076dlB_B#*dZ*VpE*gNNpfXOSaKK5vwluvE;cvQ@c%yFX1uc7D(4qA*V}seLs1SPDTQPew%lwIb zh{<#~2b#4gG*sO>;B|Nw4;^_?I#Q#+l#(G!VH)Ywl+~)XjWgj8dwAo25^9o0XB@cX z%5qu7p(bbP`Nrz+^CVie&4xnq{wrn;zjpo*_QUyi^?IA)lze^i=+b}9Pj_x?KUau$ zY0q9u6Ou%UuB)9o}9s9!Zk7hN})d*Srn#=X2l&OduCdfi})$m{qrDzA>)){|q%lY|kRm_oMHiK@nDTuxQ+h!m=Pg^rjz7yS@^^`&Qme!zns zHGTOGAZRPQQ44`Z;nBS?%&ggtT zyL9Ys=}=}OU=5w}BKtYkKj*Z4`{?XuU3OsU)r`T)s$_>2VK7q*CB{6u>Aq7QCrR=h zAn;(+<*5X(k8bd2alPXy{u3hJ3qHC^?TyKLV)oGoZ0y-02k`nPkZNf<2xl6EL)g&0 zd9hh&GGGMcj$D_+1MIw0^hWop@0n*?Z|>{0fkwN{T}-~xZuI7-*fRRsnr+$SaXU=z z*mnt^g!VRJiRDv|>0_eO0ohIMz@6xktv>uhuPM^Qmcq*TQP)<-nAZG+QXyR37H3Ab zMH|r-K+J=_ZpkXZc$K)q_fG&?<=0QuRQ)>bO1O#%Es};mcAB@~5@1suE{5M6c;6Oj z64g!OImp8^l|CcE^G8A))YR|rrsd(7d&+d(+6G+=ol8Oh3O(w@6xw7a*yniP}UJk>%RGc=*m|S`* z6-D8g!4QIZI*#8-Lm8fbx1x}TqTgRKTM<8VFrItP-$X}eTD~^Sx3!n%05z(;4?njx zi+C@1DpLWnUUsNrTvy_%9B6n|bdN1|pFF!p&4J?E-@YLQ*!}L{%K~c0x5q2@!s&{D z<@W5&0!Bq!@0k;pUTvgH4u11-mrGJ_Y>6<5v<79xwlC3b8fh0NHN~-ur8v|k?=EIi zudK(fGzJ4*z;Bg0i$-HwC1nm`^sHW})43(pZ%FqS+s@AvGyTIGI`5M!xmvL9K1-)~WW1@d zt@#uKu5jlR8%wOxTg}Hi)D!14FG9u5rrCU4&PC(F_9*I>;KlK@3RXvrfN_YMNN}sz zk--Q+FOUwPsq81fa$5|u`Qr_1aR8IQ{pZm3Jw!zbXJ1c(B7Es5ir9j5KLh)$r0mFu zET_Z-;Y6$DZbBFSS=^v5wyG5@7H!Z^ycZB}IMjG=->1wp^#-hF}MIyf}8l;Y{^_k-Y zg$%Ni#$O$x*ID%B((=|ANPS(vRN@DBr>VgSF3lGy2kDDDN5?)FLg`hyCn0~- z;c2FD%>U5fj4=G|HQ~x6#kF`Ba_p-TY(#%~uA;{TPyZn{KC^v09nz70&or_EF*)Su z=wsfJx&amaqIyaPq0yr&+HnIyt$lafcS)nM_aMys1t%VPPapYA!JysGMOqb&aH618 zGn95N@z0#z4UvWSKA!QkYpcZl3Rdr5D+Ijik$uqZ6xfpfRg^VW?wHYZVoS+dM-&)m z)Mg^0)mk@K+}e@z`s>X|Kh`a&vNM%^n)h+78IBbLzx+we?bCg^Zyfu^iKeL%Q|9tk z>)Ly4ac>~9M24V;AndMKy*~Pt`c&3y{)zJqKQ4or93kQm-+0koLCI9 zWWIC0ad3@yfHqx3XuXFd@wxrlPNqRI6;&B4MBH?WsMq-~<8p@HIf0W9{#kkyF>1y@ zb$bA)XD{Y(o9&T`uhDcJX%jwxLbfWgL``n!%%gEeMWH*J`Y$E&L>4ycH|MBj;}l|y z^B%~r1abg8MSO{B~juPV3R0}jlJ{dCBKSUXaP$QuJc6YzYG%a!;MH{eOKJytZ8 zGx%{tnazFEV`E4vEw3L~BgbDai#L!!zVT_`3c!E7Kc#0^Sg#Nxe0cr>|Ipw4NW;+7 z?oI>8vc=~;B|b@6OPK@^;t(~ZW!I$B+~LLK3Xyc3X{85+!!yeoEzcDZ?TCf1ZR&*8(F=Z&yBS&qWgF?3f*M zoPtP}<+dH^8$U6%3jCN+l>bDFH0tS`V_F1SF2-eI4ZzO~E%b1cZy-ho70M{8UH|*9 z_S)P)F3Xh%zk7il%~p)SJPGh=|DH6m?XPtzf8o$u;}z`?l>x zr6j+Y(Bufrtbc|r-Ej3?#5u1Z3tlIr%Jo@KeqEF<%rR+Aw`8ELXy zA7$XxGhwSnkm7b)X`!|D!gV6>tk6fK4+SIOIzh;)1OwM{eV`P-pT!rBqzDm?29eS` zDGfRde@9-2X#~a_HHA9^61W))aNJsikqW&$5_P0~iLWmSn52!`;V(ZUU(ZCpF_O*F zUv&?_hZTpwnEgDXRiF4ee(o`41#)=bPM~_vLl89nAKIImYt+k8YTBF$|CFoatC#92 zEmJ{`IfP1cQQndr;i6&E#9GPU7779bHSaxUXrQiBMYwOx{)ADVn66rGKl51Jr|PXe zPirRz9+SaRb6hT>DgGp*guuVO-jkS_GYmoKx~X}YQp4COwV>LsL%-_% z6Q)3EKOdRM#n!J5fByWAa!8N2sbM&zO#18J#+)BnH zH}U=$AFcaOHUD1jo#wq1NdnTZL;HL#)rdD$E$5PK>*-3Pt7IQ$tIwI=yo&iDJQTlr zq=(gsqQ6eJw5BAyKDzkYxuChC5K6*^=ETxu3BhboyyWVGPz?8c-;YireP5Z-zD=5X zGWdYOtJSaZW0&SXv@yAwP0{WJmTCPh&<|io4!K=a)TPL3uA~n=O05JQ|7>(Ht+75i z`t^=hjzmjD%ICTBkM^wz+}<8fCDX;g>-l(TcR!_4*3y>KYl(X7jYtfdZl4Rz| zK7XpvvCXrqqF6m%c=1SN2q8vEuW8KioYqBD+Jo@VMPH(~G`g-uq-*~CRp1`dMWtI@ z_&0uV2`)6sY-%+*9=<1vC;fn`hL$ZmCjZ!9nleWGB-%qC#&KH&vLX02?AA@tNO;{~ z^!tAy^*VU!iQyw%V9;>Wq2{>D_4>N_GeiRB$=t`1Jj^RGvpM1GeB_9B0f#0!KYh70x;{r%mm$jvz@H$lZQO8=Y(&xg)Ho%pU?1pxn1h#bqk-*6v5Oq=dOrs zH80No7yHM`aW$Srl?xr6UMAjR$dV{c4P6g_q;uzgXcJBkbl&hsLpWJlzK@Pw+Js~2 zROwHaW#sAT?~YhH0$pHO%c^wD$KonDnL3e7c@a3&YW4u2;$IN$&Z$H#5gXioA!aJc zaTwVlS-cia$d%0h90~?F8{aF~8`nHxCLk7F5uoh`d)k`Y_i4+}IK@Q1w<~4u#!Bga z-Bj`-PKDUnQv{=J5;Hf6nuK7Vm>^7IppkPyi$y0H?AxC>ollS$=#gr2~PB z1abUp{0}YMlybI62`C6qv@*0z=P!}6`c^I#s3U+DIKh9lT@vbv-)%Sjy=aA5gNi$E z(wN>jyS3tB!(=k2HlQ0ObW$g+H{{lI=83HI&3|%&zbS#57oyU&1wGt^%u#X)#fo^0 zdM%?*?Y=A6#yj;^&-oG>67G7V}yPYs(8gK*n+_KHa7}ls0=1Q?) zRV8Meh0rneKSq)d&I`_)dC9EMl8Ff^6BM$<j2t&Vo2r-qRfcAQf3 z^=e;zbiKDvw`G0Cru}^YrQ=mZe92vCji<#cU(1Zm~W|-q9RnbAXe!ro!IA->0?~FViw< zHF>$dPxx0&eZj$_N{1M9_&<4Zxr#QF-0gG!^@~U9{3X!@o*~E?f!ydclwY^usX=Nx|xr^dpYe!U{t8>P8>rFxXt*oR)JW;p7*S^Soo znbveS)yItHRez!Cjh84|Myw5{Ueu?cjkPt{l+X$X$R&x<^G@&^>}1Pl_z=Ey|H0bY zEi_}k8?~=Bb71Slt`n?7zMHU8Sl{047D;0*a}=yK-q8Dwy|C;^ZXnN{=d2pnWfVKN zL})wxM-hCZiF1VWOYQmkG28o4gTE0>7_-qSr%&UE=~m_!B;JLI53D~i7|=ZFn%=M9 zrBKUIrCC0GZs775Hr=!O+wi>S;HYH;AkSaq&Z4gi!#!3YrN&o6+81Kxw4opA6P+{5 zD~8R}ua|yFOv9(JMIH$brNrD<88W}QBzhilaI{dN|NUEhVPJ-v_D;DcO$_a}ikh09 z?T^9pidx#}au(Oho>%E=_O5nZ#tc7aVj}+cU$3{YST=GWS=VM2p+9?sxWXF*tmZ7% z8=byi7k(5>_@U3>zj&&l2)_@J>U>pxwXXExofWIhiMG2OHD$L=R%|6SDnv^IXwQx+ z6}(iG!StUN+`4C`iCd6$*bnS%5co;C0cvynbmT6t6P$HB!Pw}f2*DI7vNsagkf)9O zf^ngt^Da;S@q?1d+Yc0R4sh6gbIir--8i(OaP7F2t*3pp4mS?3fB0HU6S!dP3k@?i z$T1;TG%Ksfy!%=Q;ZQfjXQ{vx=K(59-`sHi9CrhVs-wx|=|s*pEh}HLVL{2U@Qf;* z{(FT_at>3~tK*r#TzS!xjn{YC?u_ zz5V>prB$@NU2x3tN20itAGFBS|F1-D+$&yCca%-mFAhIKDea#zHoxVshL-U8|8|^7 z9DM!!s_PbF zPMXC*Ss-^zf@;Sb@7q{^VT1rQ7%RW@qvXiY8fZ+wEJYiK7CZG@GsRZ!eZ@J#x7$+O z`{p!xZ@>t9Txj~0?moY4i;~+mfm;VD)utL&vddg{eiF;uAQf!9bYR2HEnbUN^pJxJ=5ex1~*CZL4>xZJF$sWq5 zBh7Qp&N%q(W5@pSOHp-nKS^`n?eP;oF+fS3?hI2YZu_V(vDxFuqsD=%Yc2L2_vs+K zZ|KUfsClmnu12{e+D4VDNdq3mgiqKf!4sYpg+!zxIISBHs|Yw zo7QZ>6~;Jv-Ss4dMiq*#{bsFr5nQeW2B+#xjUR-fHrMZ7M#&K3b%^8J>k~bz#q4$E zR2$HF*4DG56ks*84BZ|;&=V)xOHwpOxBq+JuQ4HadgXJk>GejUkCzsQ`~(*+QR?ym zb?>Aj_iUf;^Xb%H*?rg+hr5d69ddtb{Ggs2>r2s0YJsja zOzldFRdWm#gD4Qi{k@A?4J)5e53t>?Pof9*4+PJz+tzIX@p56Jj2yIunx$d9E~KtK z|GS0zR%e!=@}neo*JoEBEj2CbB(C&JRGcPF%*LGcrc~h4gTeuooMZHE0I~fJ7Kk*F zin_Q!bnVR%;<~IYTAV)K=P)@iF&tiO0RHbG5;Dbc;@B z2%TQ}u53={x@qcfnUOBNPE@_`cp<=`(oWqIB_W31&=MS7&p7Od)l;HUK8&4OYa`Ih zj!N3<3s;E|0Tl@}-g`}augne?ZoX^$K-N~k%CA}^-DW&r+iyv+?&=iJdfJK#jM8X4 z|Ja4ohGv(#4_>p%Lsi~&{8~;+Pn-s=i=39~A2#M3J--vV>TWN*klNQt zdrpPklv>Q3#{>b_LKgW}3xoiVra6|VhhGKkAA_zrkWRH#Z>Qmv8Piiw3y|GNz<+3* z4yEGkTLh3!v&K4#E2~t+w0Spt^JcI+w_NEZ6gvj}VexND=WXtW)g3yM<`h$Wk4~5V zEOal~^DD%9`>=9F*Y4bGe9EMy<~ssZ23VdVOjH+I2ou3LF{Lj67!^jnvvlzpYuM=w z?`h_tU8v(CaSg*fNQ%0u7-T+;S9r6UTKRCWeHW2rMdbWS>0aJ{k^anjrvhK4Z{JYzgvlYUyv;qLO=FbIG1y!iX47WAb~c2#e|IcyNc4;YZJpYI}}9;_OC|C4?`D# zwvP5L-iisweRfDkOf9B+yh8(2oz&pak4BHmq{GY01$i#Yh|1Z}rR3~@BI(S%(-Zxk zsunvGAe)2??TvQRO6}t;%+My=34LNIhx+e_u{2Vzb3V}F*jJoe2gt%J=SBzQ-?B=j z>;y3^?k>=ZDC%l_yPGguYTC_~Z5bw)XpoX~^ImDrFb=b3sS5~x&1{c&T_JQ$o+wfahdfe9DQU>cj_fy0oUQ+kCBL$|oQChy@%f(;b?dUBL75eAdXYqq;F%63*OI4x2jV9a z4vVEB?Gfn=D;5djmD*$?+p(oyz39ZK>Fa1z6c1WeQAP(uxlzE>%vT(>)B`R*04Kd) zN+cno2FwV#<}+hHE0Ld{Q<8RWpMgiBBN@R?E@e+A*k3PXAwG8IWzEpCLqFXo5wg7v zjmfdA7eQL$aGeVw#96KnuqX--52HPiBelD|e%3aWtJr(^KH}IRbSQ}?@z0`ID!+HB z&G3Y3{;97{txLCH;py%4CcuCFtDRF(_WLi=qUK5QninROE0sh?n7%yeUC@+%s!J6$ zo0GG{Xo^VER!&jU*}>Azg`O*Kg;$5in?6f|7O4j)F^&%H8Ky$8;(5MLLasK$h_61& zp(7Cz@Rv)MTh)f{^RM^%a8iKAUqJ+3vtE5i>2i|m3@#zcU3!2EduPXr)w_i`(sm`eEg+OB9!5IgQn{VxJ{gV0l zN0_6s4VZUJy0Dy&$Oy%<56ta8I19={IC9`ZQzPCsekm2BY{~`o*T)8(4gNr*4~<=q zvR`(Tw1m0GC6Os*SfgRCK<7G}B)30IXhZ(LsY|By-lP>7HbKX~v`^}f6EvQkP32x! z*?Wp|UkEF`83;|Wwx>t0=cNpEkj&v|7ceOIq-UIO^7fSuEdcyXass>u+uBJFpwaVe z>zsCo7eRc5Tba3-FW6IDSup8*v5({n96d{p35{1a)LgAGZO5ZNQR>izAF_AleQ&GE z(zYMDEi1%57zk%e$dZO0848~J@l{!qtH^s84d#TM@yM5^)(&z(CTH`@+l6@r;@p%l zgrW-_3Ur!Uc(xCknOMegTDk~~<4VM;-HqnRR`nYfV#k}GnG{n*nB&CVFQGyejy0Xd z-B=S7!}Se>7mn7dFP3+?MJbU@Q>>Cxxdl-_i|oPU$UUU3%2wy=13g=C_MMeJQ6ym> zfBm;>hAjPhJ699Cm1K-bKzctbKikPgZ;kj2{=)t}FqLI)Lw2vdnNncdveVf<`+cU& z0@>`&5(-qxChk6Rfx0FYFJDtg^lI5p$(BABNRb%(-1R?rHRTT;IIMVJSq1w|kZ<(d z(QN4t-|6X-k#k`U5XthxEE8VWN~PC;uche#{cOMFr`Swih)_FBmX!6(;Upb9=lX?ctJUk#Eo@*Jx;SoKXBIVOWp6uDEXNz0Z-UH}ryP z{B{xMz$=TZ{BtXM(anb$6H-~74pg?RhpQufp<(*?i@S#S}VKlfQG(`jtH6FsioD@$}<7OIl)J}juF$_! z{b(w2O;0R%$ckd^5DDI}YcB*;<;Dt-9T>Fnc1|7lD%sIZJ)iudKz0$vil&*p3)g8p zNpE_VzXb9daEgZy0wHg%6t4z95N+p{MIIoOLpU0Dm*UBFB6x$oKRRV^j z{#E7h$-jv2KhlNHTPzj&Bn?`^{%Ews#{; z(@DJr@~0vn6FYKm*6t`hL8oQk?+D##a(I2;Kjyyqbywb&7RSY+88rLnl{ixrr>#Vg zO~-}IB9G^p#pL3{#HqO|ct!blJ^h`ZwiJVp613&f$bpS3)whAqk`C%DdsDI3-RJT# z`Y(H8z5n0c4aVk$_2Mul%-^+pLqmF!S2~`OSRERdU(z_72CSb-_F{eSem*GzKV+a1 z?Tss|SPablvFY2<-n|nZ#Io+@{$wS^rb6QY86A0+*PkX){Hm_%=1Wztlt+%HGko4n z=e0a~h8Er?1{AA!tTHgQGB%u6>#`*Jvu128qjFX8r6H+u*XHx_RSG+5pU(lMg>wO? z>5)F`uVNlzu1`*MI!LP>aozB56B%N{VyD|qzo}#TEk+r)(;$bmzg89neoQd3_aX;( zefMh{V@UcQF^bMo*K=_p-{f2#Td(l_>;<3tN4^Xpv)9WeKF!O}WoI;T+c=(t;8RGK zRLT(>>YrelCY6o8vM`2i#Z%D}lix|GBicC6TChtY%>=Oz$b32HRK*NXVq)8$qV(Vv z-MS$y*~X{W?v8oi8+(mN69>OU_lGat6bwpH@;ji=<5Nxbwr@_wbb}x-N*1emI+#bWH(N^Ta_68muj+6| zE&^`uV!HFY!046v3{Z3PgpPbGyu&>L7>UHQg!S#+P>@Lrrg*-7!FQwm^QVC_Kj5zpt9CMw z(&6!Ng5$5W+JYyKh`Nd|746^|X5|lz`5)}nMbONtSIW^?5g{8yFQ3QtZ3FHqf@tQq z!%)AFs6>e;z+^s}v;g=}wB%HE#sgfr+_1r`qDu5us0-gt9@beG?q1aRq?CJD5V^{5!i}&5en_(_^zerv1*#Y2*$B`f>OIeByL=( zHKaZaw_ee!%e0q5*MppL z%8^E}<%fcu_Rz?YSHbUeM`#}woX<`a&kf%x8CRnSM2-&GsZAWd0#~NVrg$3T2x^*a z(*XGL_HOVBHgSdZ8peae*c*E9N>df4ufYZJDGYI5&+K{gZznUS8-LLjUVbX8{y9O^ zWtd6NkC8E&y@i{W09+A@b#e2veR7y7&**NOOj5tZYFJYi;Jue6o;p~`i<{i{Rc;9V zofYSeCV3q8hX#m7?B?x!xm;mEE0@ea;uQOaua!W(O4cuZ(k-lcE&qp+>V(9R3*vz5 zGQLR4G5ve4jRqFPjbdBD2r!)A67P_n8zVw3uV!iT<&KC1t66%ig|6#HMO*H|llHkp zqNAgqYmz*UZS`H&9^iX;r@@?uyf2e?0+W^K^VR|FF>dLtabr|3bmQ|c$xkKzc5jR; z6B)|f+Lt#zP>B0erLH*2x3KYxf-X{yG}DOyh5B4*-)U#EqPndMy0hA?@u@-NK{w>B z5^(PZp$>|2B^$S~+c+QT6BO|s3J|Z8BV+b6h-CJC6MXX5zR9pt?mczc^Ul%* zv)S?7AzOhTHQ%+S#sqs$=-PJBpJGp9O`Yz>ZR8bb6CX(evhRQ1{|~K;`ib?$8L7(S zSNaQ)XV~Vp!flrHhV$cgci#{0ng72&|A9T{|27+cCJO4dOX3=0WM!egPRg;)rk2m>Ivs_t^C~}u zb6GKlsMBEhOwinu!7PMvx@`^UA_$W<>0Z92vuqoqZ)r zYhYow1;`#XSYiA0Cz1JN6d74dS(yc}z{qISe5!CMKn(kkgY1gJv$yRW$bQQ;%}N zUCw@ghBS{&J_v$DM>wUB+^GyJNn9Y?Hl{UHYJqb`d%8Z2!%ynlJIiB- z#wkqa+UDDfs5q5ZX$Lmuh=o;JDYi79Z;CgCV;b)O_Ys7UWZiRzRwb*P_h5QWz?B@; z7xWn7>m$RY4TX}}A+F`?GJ1x8St<A{Wj+#$qOnq}`0H}X&#O|5yu)f| z8^oxOD^7&awn@euSQBRSK{LZe(c~Da*A7 za@fC9QltXwqmx_QBS~ryo%8nHMuPUz_S~I>4!U_`N*uHhNHMf7z<)Z)OAQnCvJ7$2NkIu+Myfz=} z_2FBBTpa}Srj%<(pz-@)t0eySK}%=M0(al<{@VMrG551B68S~F$2uOl3N*ac*5cvf z1lmSrz$P0;ljTGE%jO)s&%&RVI7L~C?OF^jFXF*mo-iIrm$CFmyR=U)|3hm}w_l!Vt=Cv5xCq;ixmhi-}T;KR+e$ILM0GD;0D?tK!Wm zlJqd|cI@Zbdaqi~e@W~-cCUZb0fMRIgeJfwWT1@Q>mtqJ|DgfPP^TtlD?+1nsA=c) zpk|c|bWhcJaklopGSiG{5ZOC;qjDk5W4mbGij}HXM}KeC5tO3E`(BkTP3-Wa{;@Ww zm#d3JFmtFKiY2v_+Wi!(H;2SYfweITpJa1UoO7R{?8Tpr)9WEo$#Qc`@_y30oHViw zOTsQg@B`a^)le91ug6UiQ|wtnj?uGV5)vmEHmWy?G?`=%;z!P-7-gENHmWZ4E*GM4OK>7j<@%|uY9 z$P>}nw&s6mf5L|hZytd)|DiGI{QeKEms^TdHV08EVX=JE+4LXUu7kQ%pCm1E%kU+i z_;TRE-nbVxI%k*p`Q(3Sd{69W&8hVLjleSx=DqTb}`c z>M>aqZTSMK01&2P7V1sx8^6Otc`$dj*n;BNcE~yFVD@r8=Xk`R65S#hz78fbh!tpqw*=gx+t)BpSn27rVAx8JkP_)7?hXEm?6m=dN>R zm}f||V7%3l4$OVV!Hh>$T=w67hRH|brr*$7v3|xKk&qxTzSrIAqKA3bK;mO(4%-xy zkZ(b60v~@i{z>_Yn@IBFyaydQ`t!ti9xe#yPhP!as`w9$Cwr(Rij-Fe`jvhlvr#|u zsBi6QWg!4O|Wbyd&vH=*GMDuK+bhkM%O z%kp_P`BY2;$727Xg_sAhTQi)Pa<2KcbTmyNlXN{%jesXMEzk}K zO2*RK`M*ZJ6OrD*!_75!kOj1`a`tg*+y^=6Pp!##L{8-K zv-&t$qT%ZEn;FCI&R)oDFO3Rp)z);c8DMj3~imG}IcD|r)S4H9Fxws%tM627LOPg@%*lyet8Pt+! z>~3}m0-^3}weX7VdTD_#&5L%m_pUD`)#aZK-&S6-86aiWUwZ2wshYu*)qhp6dc(R}gq^MU)q?9V-P`w;pj z*GRdf_%utu4)I}*_{;FuEfi$S&G8f2}$ms`f)Ux@I+22N-lIlw#z^na- zq85!N8=LgHx$2P@VF|!LI5rwR*XVA~co)1{sqhpvM`%Q0#9P3%cOg9!RPu&^K*EW= zn9U*Y9C8E7gT+Tmn1RxK@;-e!9?5`jlKO;QZd2MOd`{(ResU90MI{|8{(EkcMdxn^(wo^(bK2D7R^)4pd zqXRFNqv@nyk8nOJ`fET=p7Dc9;t}tc`g#U(-XcbVkMYl{rLQw`+fX5{AHdQs1_TW$ zieq;D&l&pqx79=|B6l>Pe~6(oYiI4tm35M=5sFv^aoIR~s|FSDM%g>sNGGyx4Q(Wj z0xSizk180J#J@qUJH}b?6H(^2tOr~qcHR&7@ssp*YQ_X?9mHs=6y3Sdb#+DPq0wvT zOt|z|xKm^wG}_CUOpfvQZ#UJmBt1-pC-euJgc{Tsv~-q(GByX=Uf6uCG>l?^fIN4t zfG)YjZ2qY?fLeNY4VK`BPgCO+zB}^k%tdRL@*MIUEiA@3ZSN6N1} zen)S=S#UybV0$P1VC|-6IzoCY4fML|!EuAv`K|`2j$GA2h4E>8=ypA72BW7@nHqmb zl#AxOn`$>_B_2B1V*bv8Hv&jqs~{BPMO5mhJ0*?qq((*&>i{}}+?r0*#8ts2UQ!#w zzjt4306>?LO#kz(6h-Us;*&x6wCVqvSTeSk_q$#XDH&;+`NHV(c1YXg4Dv7cOk=34 z?2k;j?5Yal3`JDmxcKX@I#;fby=#lgO9XLNz42Ao7(e zREcrnP5f;fy?=L0Mh9tZvM-7DeGYDX1hLVm1rY|Nm?c=~uQ!y%aRDT$`sFfx$ngS# zvf&jVoZ#XKBK{deMy|Ikeb1w7i)sZv@wLP|9wXVXANwv>r61G{RcONuLRTj3yadQuQ}l#1HLDmWOGnm`ORu5k=h>UgdSWWn=dUuccAz_lTOYhAAUe5YKlhdXFzz|?` z?1y)ldOS`yD-fpo5WiDXMSV*I6X-HChKpZiQMU&WJOvxwZq}8AaOGP+dNsW>51HUZ zk9dfXbANV7xo$n|!krYVkL%u$qU~Hbcly>`JAb{~(k#MWCLRzf!;}=4zF$1QHGMAR zYAJq}X8sBlyf5h7=c)p0$WP6;+6}B#0`&*pQhsb(`#foGr^~n6j8#lbw-F(6f)8a|vAEyqdrxkFPwG5`nu3XKz7JE_*)lu3UZenX=^$)yOp4!F5J5G5wfD{GRY2vA}W(# zR{7j1>^HrAx{|u+=dCcF0g2_wn>|10QRQE~Sf^>;Vhim*S}reAaJ)Fkc*h^7D9Z0_~Q z(j36Sp3Ps}HQN0g+d*AwUt{%9+)dTsbYDpfV_hF71)rhexG}7vzWt+a+$1 z9300R-N?O{ppxtqoCMui3MF0E z(jMT?1+Gdhy`}4qXxHtK6Rvcd-8SAQ23{`T=MdUarA0wS$hDS_kRCj33YTAOjwNE= zh+@+o54G=@2%9Ls5>mrSJ>JuaXS?IH%I-G4#1DknKQj7okIq!hp6FXkQtn5)#al2{ zTR?Bo5blz@OBh;kPPs{4qFb)ItOJhp$g@qMHyvDghYDft?1`OrkgwzSSqDE)%nTrpBnT<#cirF)jaj)Y zannyY2b#IT|bhcGz*XlHHT4B!d zzpDmt@;T$hl_`3`A<}L7Emb*hM#{ceI6g|(az^O%$@ky~2BHFfpE$$A%in}`m zDJ||^+}+*Xp}4yQDNfL!zmwmYIp25h{qEeEGjs3x=bo9Y$xO17oxS#(wO)DN=aJ<2 zv8Mo_TTeilI@GvLvrBBz;x3j-X5{oM9^@MLEd;h{rX4T0Ge^`5@*%kjElQ+>pSgw| zM4zZ7uQIfT3xDCrxZS?1?y&7P^?$c4Rx?~`W2U~xk@m*_Mv;kWD7zLI0Cul|uTTay zu?o|seqZC_qAPrF-xtU=tCmw6kvw;zw5((H?$&|y>>tM)uo zAMr6e>ekl+hqvx=%LdhS36y?a^M58N$Um5yh86ELhJ*=mIhE)u*1)6g*;7_S8r|lx z1skop=7pP;%~ian_>WKHpZR6@_lmrUp6o@J`+J@G;Z&YBo;0)~WF2 z(~y>oQ>ngde;j^!aRZn|bk#;n}4RNty%=8hqrfoQr7M!{SLeyovB zrz2lg^b(xE*?QmP$DbaOp-6ueLp4S8c} zyYxBS;;4Dq){|tMQ2}4J3>qJ?O8o}2fb$2@R&2K;1rlq&i+;#Fz8=)E`F}SINjWEl z?}-KZu-Suk@)s;^A$|OXOdOaNud2ap2FP$zgrcstyQZVw^pCP6iWk;hKBjABrf4ua;oO+=B8YPoGnZQ{$F zo>uH&WZBFBbzl2Gd zi#AmJCkmwp;wIr$zD`LHj-wZ=$ahygZ`r+_+>N?z!30lCWNwIeGz`DS&yT|Wz;>8w zWQAKdJ{QBrwE-w2`}u9&K${!U{Bs`V)%M4DF_GVu@*T>IeTaJ4yipz1i`{B)&ppr> z%-piy*p2sdX}`UZ{K-x!<`pIGvW|fep62SCm``tqyU;oI8IR;iF)o55cqyP#ujYicLxUZHLBqk^?Q9tOuyoa>gEV@UGgiu9)hT3mG=<+g zg`YIY(f#JK5TRr#xk@5sZLGN!z$cNUk{x>w>MpgwoUG_~BYZiSy6eIcgt$F$D5jClSNUMY#Tocsrrae=cd^+dgEUj@jayo0x76bdlqXP8I$EX!M6TJUqWc1b z6F>OO#QH2@c|q}n1qZw*Q%kHqySqQSXSh-LQVonc5!jNme8nT6BInafD=&JMZ_m;_ zk?Y3LU$c(0>epzflMBtP+NQHw-3!uEYv4>6y6xr9!4x04#WD2`zlJA0BBtJ_@93Pl znh2kF<0ME~x%iNf$qv_ha*~wty8+(AyHa4r zwG52?E66f5RCWo*?d9A><`v5MzlOSVdEXWP@l^Ry=;Gt%d_3C(SuL%spW>pQ+!a)F z&E>fr!RFJRH{GpL;%JJCL}EW`@BFl9=2I?u`ardg*3Jg9Y)yl`WU_>vYDY5?HsWDF z|Cw}($*P#NXSGHB$`=3bxYLrT(5VKbdsJ_3SI7Q}rD;!ea6?*2+9BqBtwZG2usFb7 zJc-!uY;|8h%5^3^dA>PMR6@@ z&1uFiO<~O=03ex?Ti4hvm&Sh)BMkyIHa!XTUg{(4xmW78Kj~$U{7-Fx)QmM$%hOpbOi3Qq_=r7rRxoIlYl<64zfx5hJ;jW5%5bS< zOHGrH=xcG7sLl2Tv=`{vu?AG1%$q2DaRQL86o}I-&miE6G?%WbTm5(N_~W z)xyRCJF1GG$UY0@5z;%Bd(BC;o0Wq&E~VdkAP43ZzF!^{c##l3!&Q!yEo}>D*ZcQu ztw=6GrPgUqR~^51Md?TQPLvumbBvFpu8aB3lxpVbuJ%9Lvt-9baf|52S_$Ykmh}-T z-fbT=n9rSUhpmmNMQ1gF4pxsPu5tU$2oXEgLo_o{FBG;h(F`Bi&92^kkO z&OqWVbSNQMnEh!3kiPPMraTNHW;YyO9t|pmL@J)IniNB<(8o3^YHguE$ z@}0EwF1Ft!ta8D`X!*AI>&Id5d(P(HdM4<6&y13JR+gZNv`w9F$vbAr5(eI-Bh_E3 z`R8^cPc(HkK7=JjkasBB%t*-=*x?#k=7pOD;i!K6kp=)U(G7?&&pgwaH-m<9-)1B7 zE_kIA$K;SI?MQ`ywF*4z`p?=#a^L3KWfn;jew; zgGCX>_bK&gKBkOBl0ZN*s;DaC((jfN_`B&Hm>^{rF*FIBU)#!WW;uGe7n4-vIQo9X zD_Ku2g1;K&S$cpPH~PLB*`X;>4_xA)Cn(Tv#Bs)lJNr=e!M)Y)h`_H!s6dB|wu9Nwk- zyy-6F9C>PZk_31WDb|7zzzHUmf{K08h@@Z|t9w9=pb zVbR&>ulOfKExyg>T*zhjoZV}1tuz_%zJ9cI zEEd$AUJ_x#V%D(IOi`;w_!SMrK*jpoO;&KD2JRj1WUMh7bS4XEP>}%OXb3B5Hq2BM zws&Q+ROUThjX0LSx~N!@QO>#j%~BA#VjB1w%)#rP{Z)*JTU~OO$4zyc%Xfhe37X~^ zCo>2T2)A_f_R~lKhTlX~>NJcrzN79|?dc&t7<<_{m+}TI=H+D_Gg%tw=t<#N>u*HA z`7xhxregJ&SygU~*gc{*7PF4RH?~cA&D3HbiD{x~u0|9==D$2=m ztlAAQ#)zdY&1vIL;KgQx>rR0?n{}uo#lLJuc^Zu6%3V4n+#>;<0 zbSy#%b`$b4_^Ph&KituMp1m(o{OtYp6%K=81f+%2=e+s98JNtl-b;Zw_%UG}guW#k zICHLq=d@WfX!&|!l*>2*HB3K$p7WJ08rGjD6@aDYZeRFWY#SmlG39dmi-v)dLHpO} z;d_@}R7+WnCyC0y(X@-x{_4ME*pchjcWr|yLEQSPQ(x+9YB)9&?Tz6Ti2`25tMV)y z^ek%@;GOCsyo9`~)1g!eT0Q{X4#TZiy%0#)A!RG@$`j-m%=mE|%plHA_XwQ!W%+YnJ z6zE6yO+IZvgto&@N$jW89CiHTk_LgNoWQ;YVxF^D4{cX9cV7rM!mfaSZxm?i&L*YT zaXqv{tqjz$nso5;|u7ZtnTNY%zsbgkM&T_%ejP}b@@7102|KEGIrlak9b&a zg*_8#&VDM443frIRyZN%ApH_PJvY0$+6!q#oDe4O)SP`5w<+|R+3s@rDLb5QgVlJm zIQ@X7`)(l^4Qs;OH_ghE9-E_d`D@9Q^J3cYIBax)0%}r`_MGpj>d;G^lm6VUcw!S@lmHL{C zUg*JcopUAuos2#{n(6Y<>qF=jUM3GSPQMpD9@B@a-54bS4<=NVIzKhq6~+d|?3a%~ zN;&Hnh}Hr5+%tu5#Esjpr?`2!#f?fC*)FiO1HBhUc-C-Jz=51V6@|9iP~YJwz99uQ zeG=U_=y6>;b8k}EPpu7Yn%aJ2^`hpH{n9YO>N_J26-HJIpJ68Bja%e<5vvMb$cuA9 z-+B3qM##qVhx34bMXA}l`Yt`)!i$I(Rf@lIMJ4w9+RsR#rM)R0S%-k{BF)r+ys4t7NjUa9@I&L&>yUQI8-kxKfR0OB~~BdfRi;_BnK{a;_c4dKkr<(!J!8wEm6 zpN7_-|M;j~;44L$(~2|Uja6D~$U79eN3&OWLBj2l)8taMy`ojr$apfrY1) zR*B|?g)5jk^~L&)SgWRZtABVz(wOxcTpofc(J&Sory}D$+c!dfKt~r|U>27c;HSS} zjBDy)w-qG)prX(*M_FR`@XFfPn3wED0f?1dbm6ezH_qn~^1w`f*V9Db88{Rj=D>BL z>D)5H#W3lOzEu1^X@8UKnpnG*`B20dE@gJCQMPO(fujZ}>fR_;WnX`ngGmA1EH&C8 zk0c@w1uHST8xX#Z#gDD2wm;a}R?Fvx#Z8S9y7rZG0FtQq`GktfOGFy0Va>xLz*erm zZEl^v4tzeQ+ktjBbquyCNTh|5wa2T(g`8Epe%kmBH*o}FI&Eg}Z_^VHY$MEF6FlDupN^>Jz zvrL6QtCYZObaW%e$91z&i0#M@%#bA(W;#NJem?b&uKJ%9Dis|QWpzT8)N2aYF zuuiyi2lK|=q53l4wXhyI@KBG(JiLA=O=Nji7yPkUf^yFRDO#A{em2Q2o(&LzS0{sl zAlkO%8e9g6Gvu!y##@j~BO>nBE8Y3_H72?UoPN;wO69JM7F#az){V`LBcTwF9l}Y1 z-wZruSuZ8~dfp#oy+sDFe06doZNQdeLJH?${<97Ms;Oy(y)OAtcU*4uD(F4T(L8Qc1mGcE4a{GATTKmG%-#}Jj8Kb#ZdD59+;QK-G3 zO|Z4~UqOs#8t$TboqyaK%tq^<&-n6lW2*)1h6QS=EJAY!*ofb4r^I_FnZjS9o+Z3?*#ZT;H``?w@i|wd zsIGJn&|4oJhIb71s3__LjJuf!zqp=E;*##Aw>~AmDHLb{x#U&iCB?8TfKH_Aq?$V0 zJX&YbCruNZFAx+Zy~z~J)60cf4avMf>0hgOW+zDN^}z>RHa1VaghKGN4{5Ez$jqL} z4Y!wG!c2@mTnxbrlKdF8e-XLKG=;5W1xoY|f5&WZZkDF&h_FUt7T|c2{Tngbm&swL zs1m(xG2b{XQUFq6uGwAR$u%H(^`>p_!C{geQ&0&J_lQgdQY7WbfXA6C$|^J3Go%0z z_L(a!<50|bo7K46ZQdqO`DDHbpv_u>P z3&Znvp>APz=U@dJvnrm!c@H9sjJ|y>W}J6nJ73Ny`nCh!dzEXxQZ3xBv7O;3?=IM} zo;D0cl6b|3EuCRTLt?wd({8T;%-UDJ(m0ib)Zg#-l!1{jZ@3?(zXT%A#s-0Gf_)OR z<*t|YPW$Z)sha^96$I~p3p2#R(hajV9MDtVrG>$zX8q{z687~1-%LchQp?NSf$n0M z4yMR=TV zwC3jWmSIM(a@hYXlu_rEvxqT^3QNR|&@iQVD3#Sz+`fkRimtinD6hDHHL&bSVZ4WK^E2AbP6)!1H6k&&- zFlFyJ3tog7im+WqdXJ0a#K>@Sj`6fsLqhf!ZVR4-lPmr0NT=3hC6$X{DK6x{KR~Re z{uE%vO6bqpasu63=xcGa#qsO}Z! zoPd$p-w^d{lD($4oJy5S()j>X5P&`}{C~*^K6w>}mn2=`5h#l&WS0CM|3L+g8zj5> z2hir9gqICH!hDK&E_q}9KN%|vQJkg$f*~%oMJ$E2=-~Qn?}q!u+B^m}rpIXOq0IcI zDs3hlVC!zuq#!PJjSj_I_Rk2tMWlFt^Ww;4E7x|9GU)0npgo&45q7$E@6a@v{!Yae!Ra)SR_90BnB58O$ z{ZtM@=)0k|0|^fj`JwmU7m!kVPj^*6{-KM!E3A_~a5j%Q0LBZ>ILDvswsi`i{fY*k zlVGh@9}$7u+JvXp2-h)sWlmJkh?#!TN<*VRko8qr-7h{eCN(KccGLb zXVNRX&_GAHsYIc6yXLaTLg8a%usyF_1yslX@qWL6Pa3CEMVrQPkV92t-Cq1nlh-^> z`MnsZk}ZK2Jm{F8gVVHSti>oa(eih*p-Mz$0&Ky_dbr-nv6+{)16m)hNj`N_2=r(4 z=oy(R)C*CLW=iB7jJqk55gx1!ZZlk!WY&56TU2<(hcUryv?Kg+M>Gj?AP1^6elew>+SCdN_0EtE6_EvkLX+#^Nx2>ttEaJLjZ|B2&j>c zD|m_s5}yRh*3?$yOkkIP!c{;^VcJWfTPw8CI|0hJax^$|lJOP`P2=(4IpMrFW1PxP z^j4$bkhvEpokTVV4bX_V{;173o8qe^u;(o@2`#xb5j)lS1=stGix0`*VYkLwSE6>@ zWx&s@5SUlu+DH;Ai&0GaoE$yggkHPd>>?JLhC;o5E{Q4cTD)4O(~1!|aRmBkb-AkJ zko+Zl`23c#M4I{c>xoazD`Pss^j{BV9yAF&h>5^6|_H1v-_3!Lzw%jPf+Gr)cDf(w$v=u-R>Ko%M1V(P$9%`?EdQOb z=g}2cwZsvQ#CXPGgm%<#DqJyj>}LOb2-2N=c_evVCtEv%73V{`^z+W z|07FuD)P(V0Iwr83dEa&P}PB;Gp>u*hAxAP(i~@vaUzG$CI#d07u| zj()Gcq{(tfesziY0tYUh%!blju!~-zwkWFa6_YL&X;=+4&?xHim|WSw0acidQz318 ztD23)6BaHXKNRFLP)0}po>YHa@JILjtP73$2e90rz8c@u4hPv&_doAuSMuTFhMv_iAUlvoCi_`qxh`7_lbheZkDaKoyi zN^Ji4Y9$^B-qS<)2VnaT;PDnhF0a(S8nwBgx3*6H;PqduZW=jia|r$@f5|$0^$U4< zB8N!*r}h17lKCFBW&Z&F4~9DPpY{vT-Z-_~IJNHn&yV>2$M=ZgefCj3TrL04SK!|) zdbs!B?Hb{GljOgm?A9@X&TtJ;Q?;YwSGqP8D;71xkEKsD2^RrUE%(({ALN0LPr7M11rKY8>Bdn?8M{M@A6<{mPd}VSXnb2=^C7u0n%nG<`F>2PP$jh~z=a)9p=N~Q zSED-F3MfMb>N)4BA{W+rPwHgfwyxLxx5!_-g;M_k9KxGgxnN z?}z^Z7{pLQUj3wA;C&e<(@0O9CGh*)yi)Z)7AANW@;{cY|BsF6|6$Sm-)H`R{V)5! zXZ!!OE&u=0!Vu4u9)&u{;c*Phf0WrOog5q~V$)+K=i>IGJs%g+|3^g*fd?M?BmYkf zGJK4-wZwNSm;AJi2?JOXZ+c3DhfqMn*@`yW=d|FI$+wu?wNj+bNlo~^>zPA2F7#JPa6f}QvHU|ZF+!>I%)b}&N*lbdzAg)0hoI>yK~|N zBzz^`isG+VZ@Cq6QMI+IC@&tI7X&$Ky$QQvIbICzDhE_ZljbF2wskeKtXtDo21mS2 zBJ^T4PtyZOY;kWW+W3C)1aZf0lHt@qo)5|^3-@G~R5@gLV{`6{R=zSXLM8J#0bbnU z`*^GB5=mJ!_mEEWaTg~y*ZR7u!3TAdM(Ymjo>H6vyrZC!!GiSQ8>}25`<#5j;;ch+ z90si^#73LdO+Q#L;QN(Rc!q@C{)imL_%w^@W_uYpH;^m@mu1<#wGoG7)ZKy$>Fb)1 zdAh%e-Qf_?-w|S%W^0g#T1}wTV)e>I2ucHUNUm_1R}~(&z1?ZvgRuz}s>$#h%5hq% zm9>aKlQ}j(b5${-gT8qJtg0jy~ zAw*a~Yd-lvyB24R05$q<>{5)-l)&H}FpZT(GQqOGV}g6?8L^Sh@8`b0yteHvCV!gE z#YVzxqj7VyO6wsP?yyn3;l1r9X|!^ZsiX&-cCT2oh1j4V^I+kMP9|}zkqNYKxahTHjjc$dBpA%> zm>g1o@Cnc5JZ{zJQ)eeN-7z~_2VP0)a1>MHgLB?^Ed-&>x5yS7oL{yTgQbLmBmD*D zGxxGgIg+WY_;4i!;YWB;Prj8FEr8e9W^MioKn5hwFY|gvvCK9;$ap zI3a=5{Q2mR|LO$+gvz3`#yjyqrhRC2qL!LSqy-9h{`p*A1OW?^&vFVS&&Who&wqwI0*F2^1+@jSaPIFg1*PE$BIVXo!h z;5pd9kpeFi$6`O>lX;-*)y5m>IZrws(kU1HuzlmP*msRw4mctw7a2!QJC+ZQ8qs5m zdi@N;+^NdP2np}dFZhdJFLfw|{4zFlo;tLRX}c&A_oNJ_U%D047gT`#%rV&7kfsb= zB_6b*ahXwfqn-wqs^}^8lSgcl!a6O=^*!x(b$@e@A8|hg$5WBfehmhY`4gSq`)B-% zL_o@F9P>QcE&laN7(okF3T-$;aL^mJcR0jC(RM@2Do_UMNSL0G(ai}7=IYsi3SYXi z3v~w%C%l|KY3D0l;0c+;X>^c6DuKIr!D++6jXnwvavqk8=VRj3w&U|}1j7Mad1V`$ zg+Uq3YF!jT=+QkEsQh$SRfanrgZe-SX3%h`5RVhhUY+kIpO_$*t>l=p*42-%yRDm`8yYb@W=(MFyA3zk~_iOOoXvh z+lk#bg7ovL;1&mAdFqYA$Aa*x$aiK&vEs+?&Y2+OVOf|9-DX>1PM(myTA?hw&J=ui zX}@oyqmhsA{ZzeOs~eV0HMK&Y`Hgmc@vdd(&t{Luj=4x`TSh3`Ykn68r?+(&M0rTX zrGCfbP1|?R(BFL$6{U;`c(y5m%b2=*Z^rSZ&F+6T5z0L;Ue}T=NQ0$IbS-q7`~wJ= zQs}Z`1!I(tK9!=3h$#`AqDJS>c1_H=3HoXdp|#7z?=G5ROE6n79(!YHMfNjds})_K zSZDuzp5Zs=-`zf1)GWuK?s$6SJi{G55ycgv+gUqezE%2gbce5!S&e=jWG3=Zc}AyG zw^R{-t=JxXH}iVBcuuOc%QPt*e~S}v5V*{D0S97zb`s`DQ}%>woaV+GVb`~pQC?|h z0EA!Y!*^JXb&TUoqk=W2gMoh~016T=ZN)LqqIs}%xy#$vdNZpk>mONTeL7-k`&y+E z7vX=o#NOw%M6gAYk#@sMeJ-z$A7(rx+r9-J>G<)&igUpti$a1$Hu%^Q9@YB9ayZiC z4zcLlSsM~={RbxspYdHsGN^dQX#-q zqX}=!KJwKiN$9WAJXjXRPB&IAoJuybLbdsc`sR`7&L7*e|LbL9^41zrVO5&_XD?B! zSlXACjmSrP@=PzS0i~bhm|Y^eqfRCsmTi4+RQ~}exiMpwBP@0nMixfs{a&b+VR^MF zy>?)!{*h3gB0F9|-hXxKqvwJ8x1vyAH&%TQOXt3ed6s)+K+8L`u%Q@6lM1gZ3c$1m zU-@9gPoJfncF-m?*jOAWM89{KbVBr(*9)#N8^I4HHu#T~>nU0(DfsxQ;8^CtUkGJ3RII0NjMn@ zz7%$mKMT)*#Y?TpJ_Vj}qwF-#pWXZexCyH?O}e9OtCr8Wz2QbUPSna;eRjTVJRHFI z*c+!Wzj|I>=x@6wvBx`S7vRC=3OpcjD>p>#V)t}`(8l?f!pslk$_1H5na$#*!~JgG z6QEB6og_Zdb+Q0(RP^u%9U@;zVEkl3bfLvrxQh-6iVatvtX!C!xuSn=1_-V)mKh8( zZ_54&{@(saEUMR6`XpMySp*-}zcYpZEDmM+$vvJ*yZ9^=*Of~cS|-(f9xz<`sQm94 z_yM<7h(n@euVi51MgKam9E64Z>wHrfM&;RTLAugcxL)!P2@_9~!AG_z*M|89Qq?)F z8b7?wf1IsPtv4Q+!`M@ zf-ugn-8AhzpJ~Lu)$E-wMSi$PZS#)`O9SMXYu3uL-;)=0_q1dXdR4i4t0il@f2!68 zA1r!S+3hQja?2BvkZng}0Ce(VNy6o`ED`3l(4fQ+y5Lv5V?V;0rK*C!lL4*n?{jca z(nI{EqtjeT)o}nS6Bh_do4V63*$(Fp)aP8bxNml@kQ;8tQt`AIOjC+<4ZT&sRB2w| zevnabZFGdz0)a?wy*U`+OwrIo__F>M%+8xX*ahErgzT^HoJ#bVCFR|Ql(;>q;3d$& zR~i{cPpv^BgRaY{S(>1+kuhOu_<}#9fRsiMHw(v0I&Kod26v|Lz>-k5K<<-Nv!!QY z64kAN8QgE!ADc0r4PBRPQ7-<)r?y|^)A8;83$di0$sYRmnJydz$Hfv4Y_iM>5f&(v zowQ|E#T9?yqM6tWa=2b2&>??Bc9iHYb1)_I zeiLLhvjO#~eP8$mfWu*CkF`EAq!&74;tJ({zEt;9hACaho6}ICOll_!^*Fg4XHw>m%6`aE&DAFfc&_cg1?Pg)+g(vD~Ag$jU zBTE&hnongIqNiC32PCSuFc=kA);Z#739;Ye`q{KLs?~i_LHX;gR_Pj=-zMdgD$7Q2 zCesug4l-*hP)hYJ!H@MH=N>|~T|-H?+^meA05RD)a2rk2D?263&lUc#%jE>1dhpN? z4zV#BD=PZ1$#!UT6kfR(m)bLYN+WbOChoaV%tCI_u%a0-h1h$R(VmLTAicx0`YP>- zTFgB{9WArYx4!)Fl?+*H$ zrbrJ`41?}^)H9-Zs#9O9Y3*OiYe~Lk+H*k?&)l5u=$T zKL-xHr4SdEDR0s`^FG-><;Xq8purp1iwkY4=aM#Y!HS9Y36JCM#i)Jz<$84KNFQgb zQ|rw-Vpe{qa!Z!5aF*AX>bwMy^P1y9*Pt}>Isx|jTZyNE-AcVx*@3zKZVZA*{chU`G4LMh%H>QosjfQgcTs;Z-#K$N zJI7_1T2y+)oK9Ry`mfyY;Kl^n^LXBt+8wrJpE>myVH}K1MHR-#-%bF)DwlzWyRQ+K z{=4^KV1!*ecpXLZN9D11;^q3PZ{ES_aGMPNfqqFY4um9Ovr`vd1!?jRErRJ^hHU+~(I~^dtOp1-+*NRYus?0l@437S9BX1GZj*d243}N&ZKSBom zNx>|ao>Q5AY^x-`JCyxN!>v^0QNCE07Cl>7U@qTM1J8@WG=uKD&}2Rq*GzVh1PU;D zQpVVtEld>g5PCnP6tc;yV8pz0SuTHOy0|~l8~fd;AEV`w2=HJy;E#JD!uvYrk0wGs z2(M7}DeXonfCbC)YBwXym)qQL(93@LFNtgUo1JW7!7T1X=kqVK!(Bz+jvMWcKY2C! zdZ7&>w;09$%;=VX!?fH*_BtfsA0TQ;>ar^YTGQ9jANO!F%JU*t9kPk)vO#S5+4uPV z=WMG_^|FZy9Ct_MwEbJi2=gw`Gxu4+#`BJDWL=k%!DQ0|6C6_raOp<$x9ldcA;%Ze zx?CF&VV@JBI8ycWvy<&NoIC9r8#~VDNCKFe_$ieT@C-gv!p_Q`Kfc6(`SF9#j5?rj z!YdWG0xLtCe*kJYF${lVPNK$#OK;wG){DO+3Yl0y^W|U>rLZ}rjxIYg1uC_MrrBRu zIP}L|(wYxq>jH;-Q@EOj%Vwilel%&RV7V$w}=u>7!IYU|a?& z;93+uH@j>>@Cp*=XsO!=r%zYTg+x6?8Ix%q1vSDffMFdF(#X)-}=A8~Ktn69qk}d}92Bn-c?7Zyf z(`B+_8*z8+h{}*<@hWSunX94zIvL=1XgNZImhdY7kP9w4k)zm=9EMDCtSYGh|rP z;1gVhtNQ3sp)hJEL}|L9o^!%E+`E1Ij9C!<=4>AByVnCxle6nLD=Q5)Jb%7o%di^b zxs#b9V-)7N8xf9^B(%qKY^F%RWOl&uq3ZKz&&az^7@zyK?v*_5SmYG(IYI5&za=*_ zzFW)&;P1|#K&7OoZ?Zq=4(9)Di_U7c^I~S6AnhesErvNA`?ytM-g(2SeJ^7M6)q14 z?`0oNt25bDCru8|ce-0PIx&1M!k+OV`Z9J@b6}}rG!@I_dv-%@6vUCYL=yZEk<9XN zSmqPw8mxK8t|W`?6XK7#hOVuLWoQc`$SZznc6kog%Tv zht(WCkJrDTznDF989`l!J{!=^NY+{~e+XSV?ebJbSoaN4^eyM=(Q4j862bF?3^v_K zaGyNQu!a?mJz$;FsMnCY$r$zAl#$mB52!D=bz1Zpux#LmVjA~Jnf1kT)rN!Y4SF~X>)G^R1Y=`iGQ7P>Vy=-iQObUeR{K~W~*)SAO>(1&<4nu zu2?nwsu=pi6bX4rwJ0p)Nf;Khn^2XxOO9=IFF?6jxs*zlfqlu?wH>IqOyZ|8=8O4+w@a((IE*v)j|v1Hsqmg zNo0R#5z&v~a6yYt7{2OTBzvq;ldnoKm(PBwF<_$ek|~og9nx+2Im0sO)J7 znzy5>pEvGodisWs0C)$R+618P!wdh$*-ha0(3GER0|yQ`o=vBQ)>#y-&6{M(E4%FC zt6TwGuxTLS?i1T8(bF9m>K_i4fjD5UtsV=!Yg3?H9XXhJhki`*iROxPC0A7Y?z~M8OW5rWTfIvyc~+efA+UB&D+g(NYU#{yk(u5Rw-{Rgl3@EL<`jf)@#(bd^ZY`&~mknG4t6t5U_UONRF65~<6if?p@vbW$s@6}ARnaI668@|);~K>$+4N)ijY%Rs zOMoJZu-M3;FN)6-i*NJpQltX z`nkg(^2ti2IJkQDTFS?lfc2_E<}*4m^LnJWNyZ)ENJt8b4`GY$wwfXZ^Ia;1bK4=x z&)%H){I23b!{X{QER|>bBXiRJ>HWgEr{LW@G&$yp(=%m&jH-z!yn7(?t}Anjz?q*86jQq#FX< zgGYx`E(bW6BV^bQWkE>hE(Q9w?eQ%08LvxMN8V8_>d^1qT@EHYtQH=zg_DuNiZ3Y- zcj+Qe!SZa4Jx3N6-XBK#<$ERn0L(DM{Ai(c0X+UBV8w<- ztv>t{7YCcS$!e2gfPUUfkBs+Aw?(H;?gg- zberr5BLDQA2QX&3JJza!B<}gzwB3UwlL_Ro7sGIOvVA+#w$gntz5yqWGU(+?qY7y*<`l!TnRupjv z2Q_yRzYp&6h9eoavmZmdUGiZ?%Q^{3y5sJf`Ex&iK5A|4wN8>_iYr&0*%$AvOZB&O zNU~~YP#&mlxQl2_H>})7nU9UF5XprVsz<3+$-o7UO2}}gg$#=}juf0KSLF(*QRA0? zi?}@i2*4KCJO|w3xxdxJiyM>*b~3W6G-U0Y2kB~|hy9g?yCK1T0NC)r zE6UPMCb{g4TSR+mPHQ8Vl4~EI2dg%&23j-0p;pa5Lc3Mi& z2io)CoVx26>uWeA!34em2@D@X9&)iuP({6TZcnE#21?TYR!W4-(6JZ8#y@gmka?Ni ziw)+3IqXcKjk`C`T4}1RHjWL~$f}zNIy*fq{mHfl=U>VV@ov=v2QH#F-z@yM%DywI zsjgc$h=|mH^cpGBi%4$?=t~ojA{`_uB2B9F7K(t>Py_^|D7{PXy$OgQy_baEgOms% z-tGIHJMI|woImGBM#f%ytv%=5$=++NIiLAVR9P@mCB1hE-#3OpA1qq_Jb|XD$wZEeQY*8ltA-%RBO^|?8S{ijwWya zjabJG4Y98e&ZyCqOh-!Wf-k&ya<6=G(k&muvk(zSg4IQOP01vkY_bOy+4~(O*bKGn zbex0N8iHm!kg8ROVJYn_Hh`?_rhFW#bgbPqNSQ6L?$j`1e@C%!po0{r!o06T8NF7M z!=_-)HeOHb6MO;GQal8za{*j-FIeWFM7voxk^N!_TOHIRl%PY+>wn}=)T7id*!Bju z;(|~?0)ZndwXhgT(RtFNwI6^7R}>|c3lwG4e@m41X%yCNPa3mmaz#yZ-e{;8g+ z^_!jqzlRQew@!b!?Du9Vo>3O!eM-0B|L8h-qAweaXYe-GoPIg(*h=H);LcXwI$A5F zQClHRk>4b{RSxn7N4V=mUp5@9VQvXS`sE}G3T^ThGSYZzy&4=CY)N~o;$8VjgF0$_ zC!232VYtk%%kjWOAwP49qaX^5; zh;~|vSC3_w*3?%|y{X*Sx=Q5y^qHcIgV^%-R{9>44R@>YSgk+%eY<>;N!$sHUgf64 z%dfOj%O-a>E~w^4b8^VDXM51Rkx+3QXObS~MYuNN$)wGMlZbFU=MyU@7F$MQR#sQI z0?rO2+A~TXxO5q|(pxI;cRRxl2SvY1?U}v|Ycj!|8Ln`5j-sG) zyO5h_qEYOk7}W@oXxBB<$~UKs?x!|)ZV#&n6+XY&ux$O~mePP8Toq@7wO^rar}aj5 z)z2jC@EX-RST~(`<;iY&b{fMnU(Mo}(kIS6kZZwH)CJFouNba$zRADc*#D)_wj_`C zLMuV!fLS#XGZWs*eJ6%paZxY$dh9%-|9r($P~wVax7X4 zHYVPpbIl3~QZVmYsjWn|@?*BTESV>vJhl*;Q#g(Kc`9tK*`E9Va|-zRXA z?QNLp_-15?$j|-N+VPvZl8v3uXXRreh&L4watGxw8wjiSBlJw9g5w&P+0AWTO z+2@a4Q^Zm}tMgH+h#_Zv(`oeDvZ6UAra z+8lb;uaj{et1voj$gee<*wZDlhcgxF=Udv-5>;O3J|8#I>A&r5Bjhe&-OPsgu(eo0 zoyjwTl3n`g9lE~VUQU`u*7{C$3n19BIn$HP>LKCQ+nR6@P~4hCuuuW67?>v1Hwz(<@dOWNfRlWY#;$cniDfGTI0am@0?Z z%5wV`EZvo?+HnLNb6DsXU{|4max^_t53adA-MO_s$gAiZ6CkK|{vJ!hFhBv;FxNK4 z!BEs;Ka3UBuXlMw(5 z=RiA6L~j-|phZzD?D(pe;lZNC&Ws!))75VC52&1~T?vG=2$Ue$T%pGcL*nE__v_G7 zbyq|{PKnW#N;4$+o)UHUMgIoCR5ivq%hT?RVc7Svdiw=;_a_ckM#1~!_*U-uLDItS zQJ;a4L;yYYo_73Tub+AJfCeM2rwuonY-i=ybkI34iE#kRqqUm57|<|-Qx#8u z{GBl<495m+p5esLbWoZ69#(l~7K`)TiOnS%8`9qm)hWh2MtqKNG*wF1Nv+%y6!Af;%z56uo&&p zsP*Y^jAhV=Qe>|-q~>a})kpXdCrQ;~Uq0cwC05Ix5s98|55LYu*ubc8FEEIZR=u@K zhDU4K<~Y;UGE7cr{oFag#6Goz|ItAWmG&;}O!w;RV8NEE1M4t$3c1}wNBZ$Tm8scS z*0PN57jB*YIdMcDmN%{w{Z-Zu98mRjC@`y9J7 z7uf{_;l^;XShjqe^pxmRvyl0IP5wiDE~+$$i;Tr5m*rZ5Uu6E4*Ew~tkOl~QS*vEw z0@jymKEzw>^th|c@YqY|q5-{mmpy283v?dHd!46XhY9V2ffeYEyLTtL8``-6$bUoS zS?ogsw>PMMa`lLC$F6YogZbi)eN*(T0+;LY_yQ`b>$t$j=c^P`2mQvy$D2+4ivZeQ zumu}?#lNUs>J96Klb>O63@8Md$sf>bGff3{f0}tTyG3+D7Vc_{m}adK*+Gq?F7`La z`k=KR_n2aI!dhWc4SCp*@u`=Z@2KhF4@82B2N?H#XOeZUlmRMha3}Hx?s+3dC*q8P zSHDry<|nKsnH}w35uERmYd3^m@9bpz1%K$RcCI(M`V|{nif!oAM1k3{qnfFYvkl{B zUeUWsSkrMKJzXAv^*$Lo!q1^CQ!wizVjK@Ue~4f#=_db=k~fhW^;+Z4)ix=bmXNKs zglQ8{e%vdp-PL0(aSyv3hCUXhNIXFG1Y@?7@{r*9_ANt;pzpWVHzG$RDnOQJfc z+Cd{|(HI!Hf~REBe$Me@i%6lY*%ph)hi;7b7h z|CcIn-)Ht*tUnAIK7Gqqrd|)z_dUp=Bt!STgE4eCWk+;S;B?KLZ_RCwI}mDlac3pw(g=x|1cwo@O&x{C03v2d-L>j-0#r{IYHRNhw zqEXzIe8=YrE)BXs-N@9r&rQjJds=->N1be=5(F8j%Gec}Kwf{Xfc1!r}*Y?`QDve{Q9 zbMU5I9Fee>wH{R-2=q0EV2iGgo8z*Tk9w$G1@dwxTkcfNjqWI}- z+CXksX!2^N>?sAutkWatxbrg{rW3T zdv#?_P#Hsw)JpA}$9F&ztmVzP={-v-ytH;02}v6-xMMKsi`ciA36#fHueN6Ad6vvq zY~*!r&NEB9`Llu;VWL=^-G|5zv1Mg0P^ZA;Su=c(XW_Z;SFA?>>fwBUa*0OiPV+{2 zLyBXejZl-SRr0>i)@;-%g-rz)Q=M19wze^pe*d9Ps zj;~J%yQr{6D<+e_@SjQGBJ=boczJQNeqUy`1Z3{b6W3Ulpa z&54>EC&<@Bz{)}LM%nvmSA3QGBjCuGOVr+sS>Eo~k#)xJ^n=+VA|^?(1E0o-e;WJ` zc!Nj(Lqh0(r!@NC1E__GaJK^u-#0WCK3lmi%#ERR5nzLNAH6wnnIQ$S{xTGL^-lG> zltwMuEv|0F6E4Vhue0TSPi-PtUqGe|@Fpx|DV3&58K(^2>=`sEyn1)WJ06{(+2T$6 zZ3id_(4Nfobx`Pi@{O*KK*2PdXKarJSA?2>o32uJ=QlPrrVomV2WQ>LZc#}RAhLPE zMG5}sBSFC(CMrZ(X0@mY5aunku&U=O1n{SS*tc409biI}>5A3VnEXm(3wQJBBVu;p z>E|7JV8AdU-v5si2XPaSU*wcPoh6*h8e?d;m55Ooocr2(z{YPu6tuJuQsDAbc2QuY z|1*D3e1ThTou0HyQ50iBgXV-Hkyd>}{hgN@25OTrXQdAvxhUaOyQxkXmBMeqaNC!z zSq^WXqz&qJ_PF9qWk<9QYvgoj1XaEH0s`#If20Xo_$0_Z#D3#n{#Y46v7qjlb>=1e z+&8MSXgfIlQAmWWuKhb>x!CgBM2XvUjDg4C^al5%I|~+a<@4h4a$iekzLvdyw%}wk zrT&tZuqD0tZQ+5y*ZpA+biR{?J$>ShZ`USc%z2DQf(7c!2GR#~WA+K~=orhRfTC@cF@KL!$`_Tnje)Gtax;_DzFK+H z?;pR7YE6-~;%w3wLNy!)2FMHP( z9Zn>(+mm3hpqjXRzu29lYj}04SabcKFJ(?EBQ%3F_x0H22=z_N>*hqr9O*Lh?V`DN zJ}vQXJ(FLawM)4&0wLyNo;t0UlMlBzh@K_(zp_k|RIYQNpomCy9^4iOkSLZJ2k-CN zuJLx5<+^_9kr-@a)^d}cl zf{2gf&QhAMaWf8Vbrr_NUL|ke$m)%o+D=b<(_@4J%X-SSMLrYd;x2A~+?OfS6|K7+ zT^mzWNIawnZqsBBEgb5W59O{-_>?qWfUcH;t?^Hwy)hyic!BRwLCsj@pB6q$Xs$Zz zK|4n)E`hl;tI=iNaw%$pR5x=X;tfKkk}Yd9UNzD8Z>XMs;A&TSB=Wgnxu2OB>8%iK zx?@K%-pt}cO8I2D&TLej>hTC|pvmZkfb(L8Ncef$uif*QD6!2L^sZnB-4^rfOquDj zeAD;J0`yvEn{BLaL=JZt0Wvz>kSPAj?y(yQ>Gu@{H*^+kP`t4U5ES@bIwTaQi>Gy_ z0cNrbuTpY1qKCyHk3z>19X=i-db0s%GzH9Vl*C_gs@2a1^HhDNd?WFo{6LR)A|x~t zGAyIl|3pn|jCkIJmhR^BAQk_q;=ttG=XTt4I;lC;KS z=Nf~v$D6^C9d!V|b2}3@>kmjNWx-ZI2e)W!9s;HfnU?FZwv7HI$CMW7r1ol=8z1j2T%Gj?JW`1N-AZ!s}tmxWI z*Ae9&gIRbbYLsf*D6!Aliln*G`XtqT-0im3)+RJ}(#t$&q@X+vmawkkF{EwPfP z**)<0>BfC<5;N~4)wmO3x$VYS=kj?H@0XOiC$h8z(~gWgsz0{{H{fB}5XlTgG`yAy zV_B@Y71qk8;AXavCt$WLDkM(SNrbd4sFeUHbNNKOOMlmL7FvW48`}bPY@f-Lx3$K( zR-1|k^~8iN#e_~s5S;!5oiP=Bli3y=Zs)`Q47`KYD>boWj%=Hf9NxxlOSEy$F8;8> z{|2p!HdQpNZN;4e^n2{A(dH8`TI%b3xZn2#kc1m}yt!}9JIM?>&YrJXMgN8!SNluK zOej3cdz0?NB~M;b81W6yv7)G|;@^c{nYS9iD<(q3Et#-vmGSP1-B!LD|y5F}eo-*weIgumjI^!M%viy*kZX-LGthuLsKa zxfKWXnUgMZ=~)`hwanw|6=}K<5S-s?tP#tw^POGkDlY2-50=!%C?!9t^@Nqe^1%1F zyVx`vj8$g}``ucdd-*K9p|WD?&=Y(PUh=mg7B6{GxX)F%WQG%);!QI#TZF%+Sn7m- zM1I%n^;S^0zuU_B;pif{n<-AfJ2m{%r<@7j(}v&K+LRw03BP{!)t}ko-M`_;ikXhh z9Z!h@Y3T*|>HkzB30Bti4YIS%xk<<-lS^Bxd*iuP{!PNk*FYET98cQkfBOXa>4F9x zoAD8}1c37UglRz^X&u==0Db9*i*Ch$|DF+371vY&@emxSj{SStT3=ErO83gN^qq&)pQNL5eNRR(92vT2!honI`NMPf{+Z`|tQPq(Pli>kO_O`|6)&Js~*H zAuD@j!Hog)dxJbAcFJEgYY%1I-bvDZm+(Twq-po<{QE-F+eY`y$Ag3df>jz-I1uc~ z40B?P+k>C(P(W~)MaRa=uA>abuqL z74#pPCmlS|mQu2Kfy`$iNiKhbs^W6JBgp!~9@jrThY};?s`}mF>t|q;($6HF05BP! zl`d=7_1fQ)b#arzXv@ndIiyoKUB;+VZwP6LBYi`z{;@@C{S${TakV(CgXS0f=&*ih zaBVLrddI#@N}J&A1ZQO?I5{1;R{T%LeZ!bv4T`%~dEd&y?^7EW^CT`jofL_GS7p^O zIVI~6Yy6!9D67iqX3t*cpZ_7<+$S$~sMTjE#)dAyu)taBpH=swwQPU;awo2Ymb0Qm z_u=2xG55yve70zVOKEg?I0U#B;y$uDJTT1QzJ0#cMAzs+=AcH!G;OB@!i;C%+iihv zK5Rta2xi=r$qjYvH^p@B3M?lH#pgU_{w=h0107|W9~OQFl5SHMT^J_n{?*ypM?|&K zU;SecL^Xy)#f zHh*9H**sZ)0kXKCC_bv?S^TPgiQkJ6zILSU*~Aw6-ROySY4u%Vg0KhkrboQLte+Qu zIxU%x{w*z*_w06QvsUVzO>yRfvwTkx{Qyn9s5uVAeQh4s;C^VWV}}05lUp(ih7}U; zm)4V~8rW}~k7(pAkJ{ewkug-LDq$;Q&a7Lf|H4cLV;^U(T@0TEm3@f{cQ`JLB%Qy+s<2K=Xe!rU7zH*K!hU;u8PgxwvH@Kx?HP`-W*C)PRg^x(%KL; znH-8|bgm`lsUK>X4A2<5ZI8{%rvnZFcHD_2s&V~15v>B7ln1%Yi{Ujs=!GWVRMygrZ-a!YbMIM8+lgjoye)~JRl&<_qpgnk`KHE z&|_ddEXVP$-fXafJb9Ud?q$rK1+!;n8&A3uAs=I;EAQ#pUxVkeaxcdZ2DC^)zs=A2 zkMqw%(coC)<~XElp|&5&%hpMxJe|vxUWO0wa_vpTY_>kw>bdv>B5D`)H>|;A0;&4$ zvAn&PF*DO%S@bmw_u-F3j+WFt#mGOOqob}_NeN^aM-`sFihOmqI($GY3WU|^WxqS! zPVTRWRbD%~sf_25^PRQRbtBxdxbtl3RUSOb3OhLk0fHS&$3TawQKQbGhYnt4(v2J+#~o zQO|HdQ9PQztZd_1|9WWCn~kGMAd~uAk5xNKWhv%hY%}KVCpX_Q;!SX0B^~Y&w(q!d zARYcbB6^{B+G`{CI5RGxMmuVpX)5IrPqzg+Av95qkZ#5Q>7@Vt8mxKmc>_E27#4>< zo~ot4{1Kf$C?sw5y!TGUZSDs#A@ZbGS3}yp`(29aXo+yzySG$iw#5Ky#2eTeAhg;C zsfp-9GGJGfCq*S=A$?T4a(PlIWlluR&Lo2Ww1$R$8vyXARmTe`3S=LcWZpYMyS}Zq zrs?$@-F1ud{T}Ke>APMPnelS*ss`t0I6i~hIUo=lCz)yM3NpP^laOaJgN15#To!7P8g5pEZfFGz zP=M2(Ic2h#1 zRXS#$hXvy}azKxAJblxO4EwyYja~-yeLJvLPb>$JsIcXYT3|A-)I7*D+}YpG&2V< z8{D{*K1%7Ws)|oxy)bPWups!Uk)ZlFEd(gS0c8LET?Zs_#-M`eqqN4y2vlg(fW{=5 zTuz|jFBdew_+Qp`-TylAe^(7jf0?WK#nSqd;ar_y2bs19baa9pr!L`uEiTruin|pFI-2D*UZy2M~wF{{c02 z3`Ku|j*4DI{MNHY{Cx2TF|7ut zyhhL#-E+JAb(4in-grCsA>^V|6^6w{>}Zj1*7mO0^xs}jciXA@*8h}ey!B<-$R7}g z&E-?$L)dhXU`?K57kAv5rC;%*;|F4w0;ZClbIc}=~|Kx0KtwevndN{?AY|Xr;k{n&vn;)U%3|#;6j~X%aR!kxX`SmJBuF& zodev$HRvKf=hOd!vlLERX-?kifxE&$&ym^6S+kt%#!u zCs^p7(w#X|5zj>{vLRHahaat$fAVi6>tr-AFOUvpTnA|0aQC76kn+u`F3;(6ZN!HB z?73p8WIHN=U!;8}hvcO}3h##l;jFiM8YN3+*{3FkVZxO-U)Xdaa}Fz>BMWzs1>v<_ z=f(NdDHkA!$Aj1*!#9Tloz2SFw8C!RmBuiqT(lX&_KcE1QxYu!YMR+P zX_-0c;w+9Y^Fn8`;em@r71@>cW{xqQKqSyFOlAIFW6!t1!Z!WD(#L;5yE{B%=~~mN zeU~wQN{Qmx=R}XQxTaz(tu)zJE{NX#y58P1Knw(zwvcg-VP1d!3Xvok)eiZ9t-vKj zQeEOgsu&Kz<#N#4XJH97kZ9+o;R4uVkxoqIk9|28@83kPkj+yT0TX9m_J!io6!eN} zV&vTMt6xNESJFspBWJEcs@JaePK(gM79;!*$Xm~oUQLa%&G&@u$7i)Gu5vMdJ-3)W z!3t$GslX?g556wb>kkN`b5{6$uOWfBB=x_-qw^qt^Naw7pkK~UH~(PTjs1u z8#watkoQ%%L8@IB3#d;c07#L)k@tjMb?;reklrxYqS9>G%?5I=+ znbDg>ZgxGrUMPLCT+wP&O~mDd#vhO{h31=5E?w`q6aM-kFP=Z zdKZ>ckbQPqaTS?opG^hN4Kii)6NW;lE#>MDa**dLud~lWG9hZ0dR~i05~=W}*H?Q0 zSJMReeZ}x|svPzf<+52QCLhvwR?=uP-Z*o_sjIKz{|8j1hv-&8Y!WnyArGVSr59-d zIHVagS-2%EdIaV7LFPg1a+XPfxp&ElO%HX@?3&u+zHB^{LT=zl`f4iAgGSBzEyDfo zFHQl)_a&tji;TfSEiJe@al}BfmFQ(hfAN=>6}AYcr4Szr@C$AHaw{)E>RzoO&-RMh zD}?tXvqbEz8BwKwRgJQpsU+B#!T&DNf6AQP3%rG$pAlsKHDb~cCHPfovEyPy4-e`7 zjA(_{T2Q!FS~38$^z~1Dw%5lo;Xuv@0bMFi(}?)72vI`0LM0ej>nPmfy0pyrK?Y!*> zcM88+H{=@6))I>BZ}1oY^%-EhkD_exzNL8=ayTWjnZdhQ!1D~h(u}|S16q+lI4>ar z5J&0X+4yL)dW>GDVJKz?z5{AgR4!Q^RbKxxb)5fjy)sm=UnR$dLeVL$ECcNyRWi+gM<)v-$zc+ zkjE_gpD1$z>5SM%2LicW2FNlbSq84N6tQ7A zQ!X<`6pWDF9zu}nA*8+FL!~NX*LH2&H|9D%LfT;hb{!d$knYls<$N~2MjC{z_AX3- zGFS8h7&~fayKUP@KZ5IWQ^ysu@>p{}_Lv2G>AGSnmK}J@j^)?YEz@YmvEBB;iXKY+_nU=ueVB!)v6u!hS(;0bJZCs=Oz`x2l_ z-~un8pspw)|3Q#&K)ucpcqlZ0M-HEC;*l>wAh$B)3sCQ8{3dqI&NsCD0BN_qWqRda z_!*K6am<(uG<@beQN;bp@~^2B>$%v74Lz>{*mBO7frVH2V_ebIn?j(?Q0KAR^-6b; zQ1qY<20Rq(BU*$jX%3ipa->8L1<*afJ%%_W0ar8dD7L);uUA(DuJ#Mvu%QcSwPQI< zzd6i_`3Bqxby04?PspJhcrzdTOl?nzvwNwDi966Bp!^!RO$bmPo<>9wm#a>SSLGjsr9|bd@^zwea>j^|wb_8J$Xe;j9mC?DBVC}Ojd$KW z3-Q>RNfs2qm^X-mr<1KPeb-pNsz_5JCzF!{PqGdY*%0NBA$TuG2;DsbKLo#is+4!8P zn`?m@oN*Xfu|)g<`L;coz$<_K18P#4Yqeq+J8yzHuS6dcKd`^FB`lC=+|`DipJMxb zXf&>C^7juiAISZ#G5iBE0J5CT#yZwn1s`V0oI}IfuREakyC`2y)=s+s=j>P;~n1hjh6$)y#I<04A@ixBfN&ZpN!(=fyQ; zG84WIDSB{)8PLi6XTAXGQvU5}{udj}t=5pe>lbA@REU9*%CV=~7bJRxxT4DzB|!2A z?1By<{tg@E^d=PM_a-P%rqbpZiK7+o!rxU7TN<|;uO}q=0O}|YbajBAP|^);1Eo1G zp}D`O_~k#Hd?tGnxQMkuLlaO7%5U>`Juh4l0k + {this.props.content} + + ); + } +} diff --git a/examples/federation/component-app/src/tool-tip.css b/examples/federation/component-app/src/tool-tip.css new file mode 100644 index 000000000..2dbed66a5 --- /dev/null +++ b/examples/federation/component-app/src/tool-tip.css @@ -0,0 +1,40 @@ +.tool-tip { + background-color: #fff; + padding: 10px 16px; + border: 1px solid #dcdfe6; + display: inline-block; + cursor: pointer; + border-radius: 4px; + position: relative; +} +/* content-box */ +.tool-tip::before { + content: attr(data-content); + max-width: 100%; + box-sizing: border-box; + position: absolute; + background-color: #303133; + color: #fff; + font-size: 12px; + border-radius: 4px; + padding: 10px; + left: 50%; + bottom: 100%; + transform: translate(-50%, -10px); + display: none; +} +/* arrow-box */ +.tool-tip::after { + display: none; + content: ''; + border: 6px solid transparent; + border-top-color: #303133; + position: absolute; + left: 50%; + bottom: 100%; + transform: translate(-50%, 2px); +} +.tool-tip:hover::after, +.tool-tip:hover::before { + display: block; +} diff --git a/examples/federation/e2e/checkApplication.spec.ts b/examples/federation/e2e/checkApplication.spec.ts new file mode 100644 index 000000000..d8a70bc1c --- /dev/null +++ b/examples/federation/e2e/checkApplication.spec.ts @@ -0,0 +1,72 @@ +import { test, expect } from '@playwright/test'; + +// Hardcoded expectations for this example app. This avoids relying on shared +// fixtures that may not exist when running the example standalone. +const APP_TEXT = { + header: 'Open Dev Tool And Focus On Network,checkout resources details', + paragraphs: { + firstStrong: 'main-app', + secondStrong: 'component-app', + }, + h4: { + buttons: 'Buttons:', + dialog: 'Dialog:', + hoverTitle: 'hover me please!', + }, + tooltip: { + content: 'hover me please', + }, + buttons: { + primaryButton: 'primary Button', + warningButton: 'warning Button', + openDialogButton: 'click me to open Dialog', + closeButton: 'close It!', + }, + dialog: { + nameMessage: 'What is your name ?', + inputValue: 'rstest', + }, +} as const; + +const COLORS = { + primaryButtonBg: 'rgb(64, 158, 255)', // #409eff + warningButtonBg: 'rgb(230, 162, 60)', // #e6a23c +} as const; + +test.describe('Complete React case', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/'); + }); + + test('Check App build and running', async ({ page }) => { + await expect(page.locator('h1')).toHaveText(APP_TEXT.header); + await expect(page.locator('strong').nth(0)).toHaveText(APP_TEXT.paragraphs.firstStrong); + await expect(page.locator('strong').nth(1)).toHaveText(APP_TEXT.paragraphs.secondStrong); + await expect(page.locator('h4').filter({ hasText: APP_TEXT.h4.buttons })).toBeVisible(); + await expect(page.locator('h4').filter({ hasText: APP_TEXT.h4.dialog })).toBeVisible(); + await expect(page.locator('h4').filter({ hasText: APP_TEXT.h4.hoverTitle })).toBeVisible(); + await expect(page.locator('.tool-tip')).toHaveText(APP_TEXT.tooltip.content); + }); + + test('Check App buttons', async ({ page }) => { + await expect(page.getByRole('button', { name: APP_TEXT.buttons.primaryButton })).toBeVisible(); + await expect(page.getByRole('button', { name: APP_TEXT.buttons.warningButton })).toBeVisible(); + await expect(page.getByRole('button', { name: APP_TEXT.buttons.openDialogButton })).toBeVisible(); + await expect(page.getByRole('button', { name: APP_TEXT.buttons.primaryButton })).toHaveCSS( + 'background-color', + COLORS.primaryButtonBg, + ); + await expect(page.getByRole('button', { name: APP_TEXT.buttons.warningButton })).toHaveCSS( + 'background-color', + COLORS.warningButtonBg, + ); + }); + + test('Check App Dialog popup', async ({ page }) => { + await page.getByRole('button', { name: APP_TEXT.buttons.openDialogButton }).click(); + await expect(page.getByRole('button', { name: APP_TEXT.buttons.closeButton })).toBeVisible(); + await expect(page.getByText(APP_TEXT.dialog.nameMessage)).toBeVisible(); + await page.fill('input', APP_TEXT.dialog.inputValue); + await page.getByRole('button', { name: APP_TEXT.buttons.closeButton }).click(); + }); +}); diff --git a/examples/federation/main-app/App.jsx b/examples/federation/main-app/App.jsx new file mode 100644 index 000000000..76f902884 --- /dev/null +++ b/examples/federation/main-app/App.jsx @@ -0,0 +1,46 @@ +import React from 'react'; +import Button from 'component-app/Button'; +import Dialog from 'component-app/Dialog'; +import ToolTip from 'component-app/ToolTip'; +export default class App extends React.Component { + constructor(props) { + super(props); + this.state = { + dialogVisible: false, + }; + this.handleClick = this.handleClick.bind(this); + this.handleSwitchVisible = this.handleSwitchVisible.bind(this); + } + handleClick(ev) { + console.log(ev); + this.setState({ + dialogVisible: true, + }); + } + handleSwitchVisible(visible) { + this.setState({ + dialogVisible: visible, + }); + } + render() { + return ( +

+

Open Dev Tool And Focus On Network,checkout resources details

+

+ react、react-dom js files hosted on main-app +

+

+ components hosted on component-app +

+

Buttons:

+ + +

hover me please!

+ +
+ ); + } +} diff --git a/examples/federation/main-app/bootstrap.js b/examples/federation/main-app/bootstrap.js new file mode 100644 index 000000000..45d0dd3c4 --- /dev/null +++ b/examples/federation/main-app/bootstrap.js @@ -0,0 +1,4 @@ +import App from './App.jsx'; +import ReactDOM from 'react-dom'; +import React from 'react'; +ReactDOM.render(, document.getElementById('app')); diff --git a/examples/federation/main-app/federated-imports.test.ts b/examples/federation/main-app/federated-imports.test.ts new file mode 100644 index 000000000..21bb7dcbb --- /dev/null +++ b/examples/federation/main-app/federated-imports.test.ts @@ -0,0 +1,10 @@ +import { expect, test } from '@rstest/core'; + +test('can import app code that uses federated module specifiers', async () => { + // This import transitively loads federated imports: + // - component-app/Button, Dialog, ToolTip + // With Module Federation configured in `rstest.config.ts` and dev servers running, + // this should load naturally (no mocks). + const mod = await import('./App.jsx'); + expect(typeof mod.default).toBe('function'); +}); diff --git a/examples/federation/main-app/index.js b/examples/federation/main-app/index.js new file mode 100644 index 000000000..d390836af --- /dev/null +++ b/examples/federation/main-app/index.js @@ -0,0 +1 @@ +import('./bootstrap.js'); diff --git a/examples/federation/main-app/package.json b/examples/federation/main-app/package.json new file mode 100644 index 000000000..d8d02b7cd --- /dev/null +++ b/examples/federation/main-app/package.json @@ -0,0 +1,30 @@ +{ + "name": "rstest_example_main-app", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "build": "rspack build --config rspack.config.js", + "serve": "serve dist -p 3002", + "start": "concurrently \"npm run build\" \"npm run serve\"", + "test": "rstest --reporter=verbose" + }, + "dependencies": { + "react": "17.0.2", + "react-dom": "17.0.2" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@rstest/core": "workspace:*", + "@module-federation/enhanced": "0.22.0", + "@module-federation/node": "^2.7.26", + "@rsbuild/plugin-react": "^1.4.2", + "@rspack/cli": "1.6.8", + "@rspack/core": "1.6.8", + "kill-port": "^2.0.1", + "concurrently": "8.2.2", + "serve": "14.2.3" + } +} diff --git a/examples/federation/main-app/public/index.html b/examples/federation/main-app/public/index.html new file mode 100644 index 000000000..432d5b45b --- /dev/null +++ b/examples/federation/main-app/public/index.html @@ -0,0 +1,12 @@ + + + + + + + Document + + +
+ + diff --git a/examples/federation/main-app/rspack.config.js b/examples/federation/main-app/rspack.config.js new file mode 100644 index 000000000..f892ff440 --- /dev/null +++ b/examples/federation/main-app/rspack.config.js @@ -0,0 +1,53 @@ +const { + HtmlRspackPlugin, +} = require('@rspack/core'); +const {ModuleFederationPlugin} = require('@module-federation/enhanced/rspack') + +const path = require('path'); +module.exports = { + entry: './index.js', + mode: 'development', + devtool: 'hidden-source-map', + output: { + publicPath: 'http://localhost:3002/', + clean: true, + }, + module: { + rules: [ + { + test: /\.(jpg|png|gif|jpeg)$/, + type: 'asset/resource', + }, + { + test: /\.(js|jsx)$/, + use: { + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { + syntax: 'ecmascript', + jsx: true, + }, + transform: { + react: { + runtime: 'automatic', + }, + }, + }, + }, + }, + }, + ], + }, + plugins: [ + new ModuleFederationPlugin({ + name: 'main_app', + remotes: { + 'component-app': 'component_app@http://localhost:3001/remoteEntry.js', + }, + }), + new HtmlRspackPlugin({ + template: './public/index.html', + }), + ], +}; diff --git a/examples/federation/main-app/rstest.config.ts b/examples/federation/main-app/rstest.config.ts new file mode 100644 index 000000000..452606e74 --- /dev/null +++ b/examples/federation/main-app/rstest.config.ts @@ -0,0 +1,97 @@ +import { ModuleFederationPlugin } from '@module-federation/enhanced/rspack'; +import { pluginReact } from '@rsbuild/plugin-react'; +import { defineConfig } from '@rstest/core'; +import path from 'node:path'; + +export default defineConfig({ + testEnvironment: 'node', + plugins: [pluginReact()], + globalSetup: ['./scripts/rstestGlobalSetup.ts'], + federation: true, + // Module Federation's Node runtime may load chunks via `fs` when running in Node. + // Ensure the test build output is written to disk so those chunks exist. + dev: { + writeToDisk: true, + }, + output: { + // Module Federation's Node runtime works best with CJS output in our test runner. + // This also ensures `__rstest_dynamic_import__` is injected as a function argument + // rather than relying on ESM `import.meta` shims. + module: false, + }, + tools: { + // Enable Rspack-level customization so federated imports like `component-app/Button` + // can be handled by the Module Federation runtime. + rspack: (config) => { + config.target = 'async-node'; + // Rstest's Node-targeted bundling config externalizes many imports. + // MF injects a loader-style request like: + // @module-federation/runtime/rspack.js!=!data:text/javascript,... + // If that gets treated as external, Node will throw ERR_INVALID_MODULE_SPECIFIER at runtime. + // Wrap externals functions to never externalize that MF runtime request. + if (config.externals) { + const externalsArr = Array.isArray(config.externals) + ? config.externals + : [config.externals]; + + config.externals = externalsArr.map((ext) => { + if (typeof ext !== 'function') return ext; + return (data: any, callback: any) => { + const req = + typeof data === 'string' + ? data + : (data && typeof data.request === 'string' ? data.request : undefined); + + if ( + typeof req === 'string' && + (req.startsWith('@module-federation/runtime/rspack.js') || + req === '@module-federation/node/runtimePlugin') + ) { + return callback(); + } + + // Rstest's node externals currently externalize unresolved specifiers as + // `node-commonjs` (to support mocks). That breaks Module Federation + // remotes like `component-app/Button` which must + // stay bundled so the MF runtime can load them from remoteEntry.js. + if ( + typeof req === 'string' && + (req === 'component-app' || + req.startsWith('component-app/')) + ) { + return callback(); + } + return (ext as any)(data, callback); + }; + }); + } + + config.output = { + ...(config.output ?? {}), + // Avoid hard-coding dev-server URLs for test builds. + publicPath: 'auto', + }; + + config.plugins ??= []; + config.plugins.push( + new ModuleFederationPlugin({ + name: 'main_app', + library: { type: 'commonjs-module', name: 'main_app' }, + remoteType: 'script', + remotes: { + // Use a Node-targeted remote build (dist-node, served on 3003). + 'component-app': 'component_app@http://localhost:3003/remoteEntry.js', + }, + // Use a local Node runtime plugin so the example runs without extra deps. + runtimePlugins: [path.resolve(__dirname, '../runtimePlugin.js')], + shared: { + react: { singleton: true, requiredVersion: '17.0.2' }, + 'react-dom': { singleton: true, requiredVersion: '17.0.2' }, + }, + }), + ); + + return config; + }, + }, +}); diff --git a/examples/federation/main-app/scripts/rstest.setup.ts b/examples/federation/main-app/scripts/rstest.setup.ts new file mode 100644 index 000000000..4c8fef77a --- /dev/null +++ b/examples/federation/main-app/scripts/rstest.setup.ts @@ -0,0 +1,211 @@ +import { spawn } from 'node:child_process'; +import { closeSync, openSync, rmSync } from 'node:fs'; +import { resolve } from 'node:path'; +import killPort from 'kill-port'; + +type TrackedChild = { + name: string; + child: ReturnType; +}; + +const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); + +const isUrlReachable = async (url: string, timeoutMs = 300) => { + const ctrl = + typeof AbortController !== 'undefined' ? new AbortController() : null; + const timer = setTimeout(() => ctrl?.abort(), timeoutMs); + try { + if (typeof fetch === 'function') { + const res = await fetch(url, { signal: ctrl?.signal }); + return res.ok; + } + } catch { + // ignore + } finally { + clearTimeout(timer); + } + return false; +}; + +const waitForUrl = async ( + url: string, + { + timeoutMs = 30_000, + intervalMs = 200, + }: { timeoutMs?: number; intervalMs?: number } = {}, +) => { + const startAt = Date.now(); + + // Retry until remoteEntry is reachable; this avoids flaky CI due to slow builds. + // Use the built-in fetch (Node 18+) if present; otherwise fall back to node:http. + while (Date.now() - startAt < timeoutMs) { + try { + if (typeof fetch === 'function') { + const res = await fetch(url); + if (res.ok) return; + } else { + const { request } = await import('node:http'); + await new Promise((resolveReq, rejectReq) => { + const req = request(url, (res) => { + if ( + res.statusCode && + res.statusCode >= 200 && + res.statusCode < 500 + ) { + resolveReq(); + } else { + rejectReq(new Error(`HTTP ${res.statusCode ?? 0}`)); + } + res.resume(); + }); + req.on('error', rejectReq); + req.end(); + }); + return; + } + } catch { + // ignore and retry + } + + // If another worker created the lock but the server never came up (or was killed), + // proactively remove the stale lock and let this worker become the owner. + if (globalThis.__RSTEST_MF_OWNER__ === false) { + const reachable = await isUrlReachable(url); + if (!reachable) { + try { + rmSync(lockFile, { force: true }); + } catch {} + } + } + + await sleep(intervalMs); + } + + throw new Error(`Timed out waiting for ${url}`); +}; + +const ensureNodeRemoteImpl = async () => { + // Fast path if already reachable. + if (await isUrlReachable(remoteEntryUrl, 500)) return; + + // Try to become the owner (cross-worker). + let fd: number | null = null; + try { + fd = openSync(lockFile, 'wx'); + globalThis.__RSTEST_MF_OWNER__ = true; + } catch (e: any) { + if (e?.code === 'EEXIST') { + // Another worker is (supposedly) starting it; wait, but allow stale lock recovery. + globalThis.__RSTEST_MF_OWNER__ = false; + await waitForUrl(remoteEntryUrl); + return; + } + throw e; + } finally { + if (fd !== null) closeSync(fd); + } + + // Owner path: build, serve, wait. + void killPort(3003).catch(() => {}); + await run(componentAppDir, 'npx', ['pnpm', 'build:node']); + globalThis.__RSTEST_MF_CHILDREN__.push( + start('component-app(node)', componentAppDir, 'npx', [ + 'pnpm', + 'serve:node', + ]), + ); + await waitForUrl(remoteEntryUrl); +}; + +declare global { + // Keep state across test files within the same worker process. + // eslint-disable-next-line no-var + var __RSTEST_MF_CHILDREN__: TrackedChild[] | undefined; + // eslint-disable-next-line no-var + var __RSTEST_MF_REGISTERED_TEARDOWN__: boolean | undefined; + // eslint-disable-next-line no-var + var __RSTEST_MF_OWNER__: boolean | undefined; +} + +const workspaceRoot = resolve(__dirname, '..', '..'); +const componentAppDir = resolve(workspaceRoot, 'component-app'); +const lockFile = resolve(workspaceRoot, '.rstest-mf-node-remote.lock'); +const remoteEntryUrl = 'http://localhost:3003/remoteEntry.js'; + +const workerEnv = { + ...process.env, + // Rstest runs workers in a stripped environment in some cases; ensure + // `npx` can find `pnpm` by adding common install locations. + PATH: [ + process.env.PATH, + '/usr/local/bin', + '/opt/homebrew/bin', + `${process.env.HOME}/.local/bin`, + ] + .filter(Boolean) + .join(':'), +}; + +const start = (name: string, cwd: string, cmd: string, args: string[]) => { + const child = spawn(cmd, args, { + cwd, + stdio: 'inherit', + env: workerEnv, + }); + return { name, child }; +}; + +const run = async (cwd: string, cmd: string, args: string[]) => { + const child = spawn(cmd, args, { cwd, stdio: 'inherit', env: workerEnv }); + await new Promise((resolveRun, rejectRun) => { + child.once('exit', (code) => { + if (code === 0) resolveRun(); + else + rejectRun( + new Error(`${cmd} ${args.join(' ')} exited with code ${code}`), + ); + }); + child.once('error', rejectRun); + }); +}; + +export const cleanupNodeRemote = async () => { + // Kill by port first (covers detached/extra processes). + await killPort(3003).catch(() => {}); + + try { + rmSync(lockFile, { force: true }); + } catch {} + + // Then kill tracked children (best effort). + for (const { child } of globalThis.__RSTEST_MF_CHILDREN__ ?? []) { + try { + child.kill('SIGTERM'); + } catch {} + } + + globalThis.__RSTEST_MF_CHILDREN__ = []; + globalThis.__RSTEST_MF_OWNER__ = false; +}; + +export const ensureNodeRemote = async () => { + // Keep state across test files within the same worker process. + globalThis.__RSTEST_MF_CHILDREN__ ??= []; + globalThis.__RSTEST_MF_OWNER__ ??= false; + + await ensureNodeRemoteImpl(); + + // Register a best-effort teardown once per process in case global teardown + // does not run (e.g. forced exit). + if ( + globalThis.__RSTEST_MF_OWNER__ && + !globalThis.__RSTEST_MF_REGISTERED_TEARDOWN__ + ) { + globalThis.__RSTEST_MF_REGISTERED_TEARDOWN__ = true; + + process.once('exit', () => { + // No awaits allowed in exit handler. + void cleanupNodeRemote(); + }); + } +}; diff --git a/examples/federation/main-app/scripts/rstestGlobalSetup.ts b/examples/federation/main-app/scripts/rstestGlobalSetup.ts new file mode 100644 index 000000000..e764ecd37 --- /dev/null +++ b/examples/federation/main-app/scripts/rstestGlobalSetup.ts @@ -0,0 +1,12 @@ +// Run once in the main process before any tests start. +// This is the stable place to boot a Module Federation node remote server; +// `setupFiles` run per test-entry and can execute concurrently across workers. +export async function setup() { + const mod = await import('./rstest.setup'); + await mod.ensureNodeRemote(); +} + +export async function teardown() { + const mod = await import('./rstest.setup'); + await mod.cleanupNodeRemote(); +} diff --git a/examples/federation/main-app/sum.test.ts b/examples/federation/main-app/sum.test.ts new file mode 100644 index 000000000..206058bfb --- /dev/null +++ b/examples/federation/main-app/sum.test.ts @@ -0,0 +1,6 @@ +import { expect, test } from '@rstest/core'; + +test('sanity: sums numbers', () => { + expect(1 + 2).toBe(3); +}); + diff --git a/examples/federation/package.json b/examples/federation/package.json new file mode 100644 index 000000000..b603fcca4 --- /dev/null +++ b/examples/federation/package.json @@ -0,0 +1,23 @@ +{ + "name": "rstest_example", + "description": "A complete Module Federation Case with React.", + "private": true, + "version": "0.0.0", + "scripts": { + "start": "pnpm --filter rstest_example_* --parallel start", + "build": "pnpm --filter rstest_example_* --parallel build", + "test": "pnpm --filter rstest_example_main-app test", + "e2e:ci": "pnpm build && pnpm exec playwright test --reporter=list" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/anderlaw/react-webpack-MF/issues" + }, + "homepage": "https://github.com/anderlaw/react-webpack-MF#readme", + "devDependencies": { + "@playwright/test": "1.57.0", + "playwright": "1.57.0" + } +} diff --git a/examples/federation/playwright.config.ts b/examples/federation/playwright.config.ts new file mode 100644 index 000000000..a1c558c2f --- /dev/null +++ b/examples/federation/playwright.config.ts @@ -0,0 +1,46 @@ +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + testDir: './e2e', + timeout: 60000, + expect: { + timeout: 15000, + }, + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 1 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: [ + ['html', { outputFolder: 'playwright-report', open: 'never' }], + ['list'], + ], + use: { + baseURL: 'http://localhost:3002', + trace: 'on-first-retry', + screenshot: 'only-on-failure', + video: 'retain-on-failure', + viewport: { width: 1920, height: 1080 }, + }, + + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + ], + + webServer: [ + { + command: 'cd component-app && pnpm serve', + port: 3001, + reuseExistingServer: !process.env.CI, + timeout: 120000, + }, + { + command: 'cd main-app && pnpm serve', + port: 3002, + reuseExistingServer: !process.env.CI, + timeout: 120000, + }, + ], +}); diff --git a/examples/federation/runtimePlugin.js b/examples/federation/runtimePlugin.js new file mode 100644 index 000000000..2888bec95 --- /dev/null +++ b/examples/federation/runtimePlugin.js @@ -0,0 +1,269 @@ +/* eslint-disable no-var */ +/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +// Local copy of the Module Federation Node runtime plugin used by our internal +// `node-host` / `node-remote` examples. We vendor it here so the federation +// example can run without depending on `@module-federation/node`. +// +// The plugin patches async-node chunk loading to support loading chunks over +// HTTP in Node (via fetch + vm/eval), and wires `__webpack_require__.l` for +// `remoteType: "script"` remotes. + +const nodeRuntimeImportCache = new Map(); + +function importNodeModule(name) { + if (!name) throw new Error('import specifier is required'); + if (nodeRuntimeImportCache.has(name)) return nodeRuntimeImportCache.get(name); + + const importModule = new Function('name', 'return import(name)'); + const promise = importModule(name) + .then((res) => res.default) + .catch((error) => { + // Remove from cache on error so it can be retried + nodeRuntimeImportCache.delete(name); + throw error; + }); + + nodeRuntimeImportCache.set(name, promise); + return promise; +} + +// webpack/rspack provides `__non_webpack_require__` for Node targets so runtime +// code can access Node's real require even when bundled. +// We intentionally reference it as a free variable (provided by the bundler). + +const resolveFile = (rootOutputDir, chunkId) => { + const path = __non_webpack_require__('path'); + return path.join(__dirname, rootOutputDir + __webpack_require__.u(chunkId)); +}; + +const returnFromCache = (remoteName) => { + try { + const globalThisVal = new Function('return globalThis')(); + const federationInstances = globalThisVal.__FEDERATION__?.__INSTANCES__ || []; + for (const instance of federationInstances) { + const moduleContainer = instance.moduleCache.get(remoteName); + if (moduleContainer?.remoteInfo) return moduleContainer.remoteInfo.entry; + } + } catch {} + return null; +}; + +const returnFromGlobalInstances = (remoteName) => { + try { + const globalThisVal = new Function('return globalThis')(); + const federationInstances = globalThisVal.__FEDERATION__?.__INSTANCES__ || []; + for (const instance of federationInstances) { + for (const remote of instance.options.remotes || []) { + if (remote.name === remoteName || remote.alias === remoteName) { + return remote.entry; + } + } + } + } catch {} + return null; +}; + +const loadFromFs = (filename, callback) => { + const fs = __non_webpack_require__('fs'); + const path = __non_webpack_require__('path'); + const vm = __non_webpack_require__('vm'); + + if (fs.existsSync(filename)) { + fs.readFile(filename, 'utf-8', (err, content) => { + if (err) return callback(err, null); + const chunk = {}; + try { + const script = new vm.Script( + `(function(exports, require, __dirname, __filename) {${content}\n})`, + { + filename, + importModuleDynamically: + // Node 20+ supports a default loader constant; fall back to dynamic import. + vm.constants?.USE_MAIN_CONTEXT_DEFAULT_LOADER ?? importNodeModule, + }, + ); + script.runInThisContext()( + chunk, + __non_webpack_require__, + path.dirname(filename), + filename, + ); + callback(null, chunk); + } catch (e) { + callback(e, null); + } + }); + } else { + callback(new Error(`File ${filename} does not exist`), null); + } +}; + +const fetchAndRun = (url, chunkName, callback, args) => { + (typeof fetch === 'undefined' + ? importNodeModule('node-fetch').then((mod) => mod.default) + : Promise.resolve(fetch) + ) + .then((fetchFunction) => { + // Allow MF runtime hooks to intercept fetch. + return args?.origin?.loaderHook?.lifecycle?.fetch + ?.emit(url.href, {}) + .then((res) => { + if (!res || !(res instanceof Response)) { + return fetchFunction(url.href).then((response) => response.text()); + } + return res.text(); + }); + }) + .then((data) => { + const chunk = {}; + try { + // eslint-disable-next-line no-eval + eval(`(function(exports, require, __dirname, __filename) {${data}\n})`)( + chunk, + __non_webpack_require__, + url.pathname.split('/').slice(0, -1).join('/'), + chunkName, + ); + callback(null, chunk); + } catch (e) { + callback(e, null); + } + }) + .catch((err) => callback(err, null)); +}; + +const resolveUrl = (remoteName, chunkName) => { + try { + return new URL(chunkName, __webpack_require__.p); + } catch { + const entryUrl = returnFromCache(remoteName) || returnFromGlobalInstances(remoteName); + if (!entryUrl) return null; + + const url = new URL(entryUrl); + const path = __non_webpack_require__('path'); + + const urlPath = url.pathname; + const lastSlashIndex = urlPath.lastIndexOf('/'); + const directoryPath = + lastSlashIndex >= 0 ? urlPath.substring(0, lastSlashIndex + 1) : '/'; + + const rootDir = __webpack_require__.federation?.rootOutputDir || ''; + const combinedPath = path.join(directoryPath, rootDir, chunkName).replace(/\\/g, '/'); + return new URL(combinedPath, url.origin); + } +}; + +const loadChunk = (strategy, chunkId, rootOutputDir, callback, args) => { + if (strategy === 'filesystem') { + return loadFromFs(resolveFile(rootOutputDir, chunkId), callback); + } + + const url = resolveUrl(rootOutputDir, chunkId); + if (!url) return callback(null, { modules: {}, ids: [], runtime: null }); + + fetchAndRun(url, chunkId, callback, args); +}; + +const installChunk = (chunk, installedChunks) => { + for (const moduleId in chunk.modules) { + __webpack_require__.m[moduleId] = chunk.modules[moduleId]; + } + if (chunk.runtime) chunk.runtime(__webpack_require__); + for (const chunkId of chunk.ids) { + if (installedChunks[chunkId]) installedChunks[chunkId][0](); + installedChunks[chunkId] = 0; + } +}; + +const deleteChunk = (chunkId, installedChunks) => { + delete installedChunks[chunkId]; + return true; +}; + +const setupScriptLoader = () => { + __webpack_require__.l = (url, done, key, chunkId) => { + if (!key || chunkId) throw new Error(`__webpack_require__.l name is required for ${url}`); + __webpack_require__.federation.runtime + .loadScriptNode(url, { attrs: { globalName: key } }) + .then((res) => { + const enhancedRemote = __webpack_require__.federation.instance.initRawContainer( + key, + url, + res, + ); + new Function('return globalThis')()[key] = enhancedRemote; + done(enhancedRemote); + }) + .catch(done); + }; +}; + +const setupChunkHandler = (installedChunks, args) => { + return (chunkId, promises) => { + let installedChunkData = installedChunks[chunkId]; + if (installedChunkData !== 0) { + if (installedChunkData) { + promises.push(installedChunkData[2]); + } else { + const matcher = __webpack_require__.federation.chunkMatcher + ? __webpack_require__.federation.chunkMatcher(chunkId) + : true; + if (matcher) { + const promise = new Promise((resolve, reject) => { + installedChunkData = installedChunks[chunkId] = [resolve, reject]; + + const fs = + typeof process !== 'undefined' ? __non_webpack_require__('fs') : false; + const filename = + typeof process !== 'undefined' + ? resolveFile(__webpack_require__.federation.rootOutputDir || '', chunkId) + : false; + + if (fs && fs.existsSync(filename)) { + loadChunk('filesystem', chunkId, __webpack_require__.federation.rootOutputDir || '', (err, chunk) => { + if (err) return deleteChunk(chunkId, installedChunks) && reject(err); + if (chunk) installChunk(chunk, installedChunks); + resolve(chunk); + }, args); + } else { + const chunkName = __webpack_require__.u(chunkId); + const loadingStrategy = typeof process === 'undefined' ? 'http-eval' : 'http-vm'; + loadChunk(loadingStrategy, chunkName, __webpack_require__.federation.initOptions.name, (err, chunk) => { + if (err) return deleteChunk(chunkId, installedChunks) && reject(err); + if (chunk) installChunk(chunk, installedChunks); + resolve(chunk); + }, args); + } + }); + promises.push((installedChunkData[2] = promise)); + } else { + installedChunks[chunkId] = 0; + } + } + } + }; +}; + +const setupWebpackRequirePatching = (handle) => { + if (__webpack_require__.f) { + if (__webpack_require__.f.require) __webpack_require__.f.require = handle; + if (__webpack_require__.f.readFileVm) __webpack_require__.f.readFileVm = handle; + } +}; + +module.exports = function nodeRuntimePlugin() { + return { + name: 'node-federation-plugin', + beforeInit(args) { + (() => { + const installedChunks = {}; + setupScriptLoader(); + const handle = setupChunkHandler(installedChunks, args); + setupWebpackRequirePatching(handle); + })(); + return args; + }, + }; +}; diff --git a/package.json b/package.json index 066d19cc6..5673bd0d2 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "format": "biome check --write && prettier --write '**/*.{md,mdx,css,less,scss,json,jsonc,json5}' && heading-case --write", "lint": "biome check . --diagnostic-level=warn && pnpm run check-spell && pnpm lint:type", "lint:type": "rslint", - "prepare": "pnpm run build && simple-git-hooks" + "prepare": "pnpm run build && simple-git-hooks", + "test:feederation": "pnpm -C examples/federation test" }, "simple-git-hooks": { "pre-commit": "npx nano-staged" diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index b6fadf621..87088149c 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -180,6 +180,7 @@ const createDefaultConfig = (): NormalizedConfig => ({ logHeapUsage: false, bail: 0, includeTaskLocation: false, + federation: false, browser: { enabled: false, provider: 'playwright', @@ -219,6 +220,13 @@ export const withDefaultConfig = (config: RstestConfig): NormalizedConfig => { merged.setupFiles = castArray(merged.setupFiles); merged.globalSetup = castArray(merged.globalSetup); + // Module Federation (async-node) runs most reliably with CJS output in our + // worker VM runtime, because some third-party runtimes evaluate chunks via + // vm/eval and rely on a global `__rstest_dynamic_import__` fallback. + if (merged.federation && merged.output?.module == null) { + merged.output = { ...(merged.output ?? {}), module: false }; + } + merged.exclude.patterns.push(TEMP_RSTEST_OUTPUT_DIR_GLOB); const reportsDirectory = formatRootStr( diff --git a/packages/core/src/core/plugins/mockRuntimeCode.js b/packages/core/src/core/plugins/mockRuntimeCode.js index 51f032c3e..6cccbe472 100644 --- a/packages/core/src/core/plugins/mockRuntimeCode.js +++ b/packages/core/src/core/plugins/mockRuntimeCode.js @@ -1,6 +1,31 @@ /** biome-ignore-all lint/complexity/useArrowFunction: */ // Rstest runtime code should be prefixed with `rstest_` to avoid conflicts with other runtimes. +// Some async-node outputs (including Module Federation runtimes) are externalized to +// `__rstest_dynamic_import__()`. Those chunks can be evaluated via vm/eval +// and will not have access to the worker's function-argument injection. Provide a +// safe default that relies on Node's native dynamic import. +// +// The worker will still override this with a richer implementation when available. +try { + globalThis.__rstest_dynamic_import__ = + globalThis.__rstest_dynamic_import__ || + function (specifier, importAttributes) { + return import(specifier, importAttributes); + }; + // Ensure an unscoped identifier exists for strict-mode evaluated scripts. + // This must be done via the main context so that code evaluated later via + // vm/eval can reference `__rstest_dynamic_import__`. + // eslint-disable-next-line no-var + var __rstest_dynamic_import__ = globalThis.__rstest_dynamic_import__; + try { + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('vm').runInThisContext( + 'var __rstest_dynamic_import__ = globalThis.__rstest_dynamic_import__', + ); + } catch {} +} catch {} + const originalWebpackRequire = __webpack_require__; __webpack_require__ = new Proxy( function (...args) { @@ -16,6 +41,31 @@ __webpack_require__ = new Proxy( }, { set(target, property, value) { + // Ensure chunk handler placeholders never throw before federation runtime + // initializes. The bundler assigns `__webpack_require__.f = {}` early and + // later runtimes do `__webpack_require__.f.consumes = __webpack_require__.f.consumes || thrower`. + // Pre-seeding those keys prevents the thrower from being installed. + if (property === 'f' && value && typeof value === 'object') { + value.consumes ??= function () {}; + value.remotes ??= function () {}; + + // Module Federation's Node runtime plugin may try to patch chunk loading + // handlers like `readFileVm` / `require` to load chunks via native require. + // That breaks Rstest because chunks must be evaluated inside the same + // runtime instance to preserve mocks and shims. + // + // Wrap `__webpack_require__.f` so once Rspack installs our chunk loader, + // it can't be replaced by other runtimes. + value = new Proxy(value, { + set(obj, key, val) { + if ((key === 'readFileVm' || key === 'require') && obj[key]) { + return true; + } + obj[key] = val; + return true; + }, + }); + } target[property] = value; originalWebpackRequire[property] = value; return true; @@ -32,6 +82,23 @@ __webpack_require__ = new Proxy( __webpack_require__.rstest_original_modules = {}; __webpack_require__.rstest_original_module_factories = {}; +// Module Federation can attach placeholder chunk handlers during bootstrap that +// are later overridden by the federation runtime once it initializes. Our test +// runtime eagerly calls `__webpack_require__.e()` which iterates over all +// `__webpack_require__.f[...]` handlers; if any handler is still a placeholder +// that throws, chunk loading will fail before federation has a chance to patch +// it. Make placeholder handlers no-ops until the real runtime replaces them. +const __rstest_noop_chunk_handler__ = function () {}; +if (typeof __webpack_require__.f === 'object' && __webpack_require__.f) { + for (const k of ['consumes', 'remotes']) { + if (typeof __webpack_require__.f[k] !== 'function') continue; + const src = Function.prototype.toString.call(__webpack_require__.f[k]); + if (src.includes('should have __webpack_require__.f.')) { + __webpack_require__.f[k] = __rstest_noop_chunk_handler__; + } + } +} + //#region rs.unmock __webpack_require__.rstest_unmock = (id) => { const originalModuleFactory = diff --git a/packages/core/src/core/rsbuild.ts b/packages/core/src/core/rsbuild.ts index f7958a0c6..01231be8b 100644 --- a/packages/core/src/core/rsbuild.ts +++ b/packages/core/src/core/rsbuild.ts @@ -68,7 +68,7 @@ export const prepareRsbuild = async ( ): Promise => { const { command, - normalizedConfig: { isolate, dev = {}, coverage }, + normalizedConfig: { isolate, dev = {}, coverage, federation }, } = context; // Filter out browser mode projects - this rsbuild is for node mode only @@ -78,7 +78,9 @@ export const prepareRsbuild = async ( const debugMode = isDebug(); RsbuildLogger.level = debugMode ? 'verbose' : 'error'; - const writeToDisk = dev.writeToDisk || debugMode; + // Module Federation's Node runtime can load chunks via fs/vm, so the test build + // artifacts need to exist on disk (even though rsbuild runs in middlewareMode). + const writeToDisk = dev.writeToDisk || debugMode || Boolean(federation); const rsbuildInstance = await createRsbuild({ callerName: 'rstest', diff --git a/packages/core/src/runtime/worker/loadEsModule.ts b/packages/core/src/runtime/worker/loadEsModule.ts index 806d65f93..5cf260fe1 100644 --- a/packages/core/src/runtime/worker/loadEsModule.ts +++ b/packages/core/src/runtime/worker/loadEsModule.ts @@ -208,8 +208,7 @@ export const loadModule = async ({ meta.url = pathToFileURL( distPath.endsWith('rstest-runtime.mjs') ? distPath : testPath, ).toString(); - // @ts-expect-error - meta.__rstest_dynamic_import__ = defineRstestDynamicImport({ + const rstestDynamicImport = defineRstestDynamicImport({ assetFiles, testPath, distPath: distPath || testPath, @@ -218,6 +217,17 @@ export const loadModule = async ({ esmMode: EsmMode.Unknown, }); // @ts-expect-error + meta.__rstest_dynamic_import__ = rstestDynamicImport; + + // Some Node runtimes may evaluate chunks outside of the SourceTextModule + // context (e.g. via eval/vm wrappers). Expose the shim globally as a + // fallback so those chunks can still resolve externals. + try { + (globalThis as any).__rstest_dynamic_import__ = rstestDynamicImport; + } catch { + // ignore + } + // @ts-expect-error meta.readWasmFile = ( wasmPath: URL, callback: (err: Error | null, data?: Buffer) => void, diff --git a/packages/core/src/runtime/worker/loadModule.ts b/packages/core/src/runtime/worker/loadModule.ts index 74549be0b..1dbcacb2c 100644 --- a/packages/core/src/runtime/worker/loadModule.ts +++ b/packages/core/src/runtime/worker/loadModule.ts @@ -1,4 +1,5 @@ import { createRequire as createNativeRequire } from 'node:module'; +import fs from 'node:fs'; import { isAbsolute } from 'node:path'; import { pathToFileURL } from 'node:url'; import vm from 'node:vm'; @@ -38,22 +39,32 @@ const createRequire = ( const joinedPath = isRelativePath(id) ? path.join(currentDirectory, id) : id; + const normalizedJoinedPath = path.normalize(joinedPath); - const content = assetFiles[joinedPath] || latestAssetFiles[joinedPath]; + // Prefer in-memory assets produced by the bundler (dev server output). + // For Module Federation / async-node, runtime may `require()` chunks from disk, + // so fall back to reading from filesystem to keep evaluation inside our VM + // wrapper (ensures `__rstest_dynamic_import__` and other shims exist). + const content = + assetFiles[normalizedJoinedPath] || + latestAssetFiles[normalizedJoinedPath] || + (isRelativePath(id) && fs.existsSync(normalizedJoinedPath) + ? fs.readFileSync(normalizedJoinedPath, 'utf8') + : undefined); if (content) { try { return cacheableLoadModule({ codeContent: content, - testPath: joinedPath, - distPath: joinedPath, + testPath: normalizedJoinedPath, + distPath: normalizedJoinedPath, rstestContext, assetFiles, interopDefault, }); } catch (err) { logger.error( - `load file ${joinedPath} failed:\n`, + `load file ${normalizedJoinedPath} failed:\n`, err instanceof Error ? err.message : err, ); } @@ -222,6 +233,28 @@ export const loadModule = ({ ...rstestContext, }; + // Some runtimes (notably Module Federation's Node runtime plugin) may evaluate code + // via `vm`/`eval` wrappers that do not preserve the function-argument injection + // we do below. Expose the dynamic import shim on globalThis as a fallback so + // those evaluated chunks can still resolve external modules. + // + // This is intentionally best-effort and scoped to the worker process. + try { + (globalThis as any).__rstest_dynamic_import__ = context.__rstest_dynamic_import__; + } catch { + // ignore + } + try { + // Ensure a global binding exists for strict-mode scripts evaluated via vm/eval. + // Note: assigning on globalThis alone is not enough because evaluated scripts + // may refer to an unscoped identifier `__rstest_dynamic_import__`. + vm.runInThisContext( + 'globalThis.__rstest_dynamic_import__ = globalThis.__rstest_dynamic_import__ || undefined; var __rstest_dynamic_import__ = globalThis.__rstest_dynamic_import__', + ); + } catch { + // ignore + } + const codeDefinition = `'use strict';(${Object.keys(context).join(',')})=>{`; const code = `${codeDefinition}${codeContent}\n}`; diff --git a/packages/core/src/types/config.ts b/packages/core/src/types/config.ts index af5877b59..e0ad28663 100644 --- a/packages/core/src/types/config.ts +++ b/packages/core/src/types/config.ts @@ -334,6 +334,17 @@ export interface RstestConfig { */ browser?: BrowserModeConfig; + /** + * Enable Module Federation compatibility mode for Node tests. + * + * When enabled, Rstest will apply some additional defaults to better support + * Module Federation runtimes that load chunks via Node fs/vm/eval and/or + * HTTP at runtime. + * + * @default false + */ + federation?: boolean; + /** * Coverage options */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9bbfbe4d3..cbf079567 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -461,6 +461,102 @@ importers: specifier: ^5.9.3 version: 5.9.3 + examples/federation: + devDependencies: + '@playwright/test': + specifier: 1.57.0 + version: 1.57.0 + playwright: + specifier: 1.57.0 + version: 1.57.0 + + examples/federation/component-app: + dependencies: + react: + specifier: ^17.0.2 + version: 17.0.2 + react-dom: + specifier: ^17.0.2 + version: 17.0.2(react@17.0.2) + devDependencies: + '@module-federation/enhanced': + specifier: 0.22.0 + version: 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@rspack/cli': + specifier: 1.6.8 + version: 1.6.8(@rspack/core@1.6.8(@swc/helpers@0.5.18))(@types/express@4.17.25)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@rspack/core': + specifier: 1.6.8 + version: 1.6.8(@swc/helpers@0.5.18) + concurrently: + specifier: 8.2.2 + version: 8.2.2 + serve: + specifier: 14.2.3 + version: 14.2.3 + + examples/federation/lib-app: + dependencies: + react: + specifier: ^17.0.2 + version: 17.0.2 + react-dom: + specifier: ^17.0.2 + version: 17.0.2(react@17.0.2) + devDependencies: + '@module-federation/enhanced': + specifier: 0.22.0 + version: 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@rspack/cli': + specifier: 1.6.8 + version: 1.6.8(@rspack/core@1.6.8(@swc/helpers@0.5.18))(@types/express@4.17.25)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@rspack/core': + specifier: 1.6.8 + version: 1.6.8(@swc/helpers@0.5.18) + concurrently: + specifier: 8.2.2 + version: 8.2.2 + serve: + specifier: 14.2.3 + version: 14.2.3 + + examples/federation/main-app: + dependencies: + react: + specifier: 17.0.2 + version: 17.0.2 + react-dom: + specifier: 17.0.2 + version: 17.0.2(react@17.0.2) + devDependencies: + '@module-federation/enhanced': + specifier: 0.22.0 + version: 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@module-federation/node': + specifier: ^2.7.26 + version: 2.7.26(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@rsbuild/plugin-react': + specifier: ^1.4.2 + version: 1.4.2(@rsbuild/core@1.7.1) + '@rspack/cli': + specifier: 1.6.8 + version: 1.6.8(@rspack/core@1.6.8(@swc/helpers@0.5.18))(@types/express@4.17.25)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@rspack/core': + specifier: 1.6.8 + version: 1.6.8(@swc/helpers@0.5.18) + '@rstest/core': + specifier: workspace:* + version: link:../../../packages/core + concurrently: + specifier: 8.2.2 + version: 8.2.2 + kill-port: + specifier: ^2.0.1 + version: 2.0.1 + serve: + specifier: 14.2.3 + version: 14.2.3 + examples/node: devDependencies: '@rstest/core': @@ -596,7 +692,7 @@ importers: dependencies: antd: specifier: ^5.29.1 - version: 5.29.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + version: 5.29.3(date-fns@2.30.0)(luxon@3.7.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) birpc: specifier: 2.9.0 version: 2.9.0 @@ -1196,6 +1292,10 @@ packages: resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} engines: {node: '>=6.9.0'} + '@babel/core@7.24.7': + resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==} + engines: {node: '>=6.9.0'} + '@babel/core@7.28.3': resolution: {integrity: sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==} engines: {node: '>=6.9.0'} @@ -1482,6 +1582,10 @@ packages: resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} engines: {node: '>=18'} + '@discoveryjs/json-ext@0.5.7': + resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} + engines: {node: '>=10.0.0'} + '@docsearch/core@4.4.0': resolution: {integrity: sha512-kiwNo5KEndOnrf5Kq/e5+D9NBMCFgNsDoRpKQJ9o/xnSlheh6b8AXppMuuUVVdAUIhIfQFk/07VLjjk/fYyKmw==} peerDependencies: @@ -1642,6 +1746,9 @@ packages: peerDependencies: tslib: '2' + '@leichtgewicht/ip-codec@2.0.5': + resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -1670,12 +1777,88 @@ packages: '@microsoft/tsdoc@0.16.0': resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} + '@module-federation/bridge-react-webpack-plugin@0.22.0': + resolution: {integrity: sha512-OzMBBbUhOMbDVX/wkVDxaOshgyUdxv+kRQDtxl1/ipV5GXTjs1tpS4NHtDwiJi0qKeG0AvnvGCrPu7bjMOcAVw==} + + '@module-federation/cli@0.22.0': + resolution: {integrity: sha512-kdeDg6HuOqJYKtPeoupWQg6wLZT7B+AwMDwMjwhcKHxKEmKFPImbJLymBWEgmKTktZKh1ERtEOplwFt9u5iEBA==} + engines: {node: '>=16.0.0'} + hasBin: true + + '@module-federation/data-prefetch@0.22.0': + resolution: {integrity: sha512-NESR/5Wcn9unPY18oQSSXlbXTnMbUFwqqvSZnpJt5vBb/8QlcJEiPnxERZqKhKrIS6GTD8KneHPRCOQsP6Xcqw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@module-federation/dts-plugin@0.22.0': + resolution: {integrity: sha512-lj5YtUZz0moaT1XziM0OyizE0mIhMa8W65RUiX/+UZ4iNK/KMs4e/CGpfhEt2Lj9+j6KYSzI2+676d+73j/kag==} + peerDependencies: + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: '>=1.0.24' + peerDependenciesMeta: + vue-tsc: + optional: true + + '@module-federation/enhanced@0.22.0': + resolution: {integrity: sha512-OysyO6xbhpP+CeOEDp2v6HyFcVT5wWAdQrfga3jhlFUAdIR7nZZ2albysnF2CGn/xyU050Ss74ttgy7GiKi5fQ==} + hasBin: true + peerDependencies: + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: '>=1.0.24' + webpack: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + vue-tsc: + optional: true + webpack: + optional: true + '@module-federation/error-codes@0.21.6': resolution: {integrity: sha512-MLJUCQ05KnoVl8xd6xs9a5g2/8U+eWmVxg7xiBMeR0+7OjdWUbHwcwgVFatRIwSZvFgKHfWEiI7wsU1q1XbTRQ==} '@module-federation/error-codes@0.22.0': resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} + '@module-federation/inject-external-runtime-core-plugin@0.22.0': + resolution: {integrity: sha512-zeN6XiLV9l0tAsZzQxHLEQM28sWiijmIBp9CiIDc4iqk2f/kgCSqiBWTiNcS4sZODzupPkktaWsC5+5eWk0ENQ==} + peerDependencies: + '@module-federation/runtime-tools': 0.22.0 + + '@module-federation/managers@0.22.0': + resolution: {integrity: sha512-Ptv8gEUihPBeoQEpsKq3GZUEB4y/hqG83mKw5NrKpXMIfcoF6SZjcknXz5LuN7NF3xMi1XHYU74z/nKzr+izew==} + + '@module-federation/manifest@0.22.0': + resolution: {integrity: sha512-Exv+frMkRGKDs3KKXeBBKcHvL7nNTk5Yt2ftEvxCUIRPC16Ebvy6RcQvFFvbvmOhuM/If6j6E/aZu5Z9oau6xw==} + + '@module-federation/node@2.7.26': + resolution: {integrity: sha512-C7aIABSxbZKOvVDMIivmV9Q/aOVh9xpUv+y+nwSWuQr9v2pgmMzVK3rxWoeusmkpaENia8h5AWNpYjcrMi+O9g==} + peerDependencies: + next: '*' + react: ^16||^17||^18||^19 + react-dom: ^16||^17||^18||^19 + webpack: ^5.40.0 + peerDependenciesMeta: + next: + optional: true + react: + optional: true + react-dom: + optional: true + + '@module-federation/rspack@0.22.0': + resolution: {integrity: sha512-PvDlFxzCbufArZvt6wSLsJNm20hdDsz/4X04YAxAZfp/dTECZghZsebLcR7nHOzOwR2gCX8vv+gB3r+5MheobA==} + peerDependencies: + '@rspack/core': '>=0.7' + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: '>=1.0.24' + peerDependenciesMeta: + typescript: + optional: true + vue-tsc: + optional: true + '@module-federation/runtime-core@0.21.6': resolution: {integrity: sha512-5Hd1Y5qp5lU/aTiK66lidMlM/4ji2gr3EXAtJdreJzkY+bKcI5+21GRcliZ4RAkICmvdxQU5PHPL71XmNc7Lsw==} @@ -1700,6 +1883,9 @@ packages: '@module-federation/sdk@0.22.0': resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} + '@module-federation/third-party-dts-extractor@0.22.0': + resolution: {integrity: sha512-3y2DZdeEjArNKDqA1Ds32Q6A5RATcsmywCXyQaWcfaScprpmzfEWiDkeD/nzoA/0+4ePY8OEinJ4hLtoMNLbLQ==} + '@module-federation/webpack-bundler-runtime@0.21.6': resolution: {integrity: sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ==} @@ -1961,6 +2147,11 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@playwright/test@1.57.0': + resolution: {integrity: sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==} + engines: {node: '>=18'} + hasBin: true + '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} @@ -2267,6 +2458,12 @@ packages: '@rspack/binding@1.7.0': resolution: {integrity: sha512-xO+pZKG2dvU9CuRTTi+DcCc4p+CZhBJlvuYikBja/0a62cTntQV2PWV+/xU1a6Vbo89yNz158LR05nvjtKVwTw==} + '@rspack/cli@1.6.8': + resolution: {integrity: sha512-pFMYsov8Av7bNWEU9l0HCTk2A5vOPaaZBkZSkCs68U07tkMOQ58IvUiC5Uy1B780bqE2jBt/b6yA41uNmXScZg==} + hasBin: true + peerDependencies: + '@rspack/core': ^1.0.0-alpha || ^1.x + '@rspack/core@1.6.8': resolution: {integrity: sha512-FolcIAH5FW4J2FET+qwjd1kNeFbCkd0VLuIHO0thyolEjaPSxw5qxG67DA7BZGm6PVcoiSgPLks1DL6eZ8c+fA==} engines: {node: '>=18.12.0'} @@ -2285,6 +2482,12 @@ packages: '@swc/helpers': optional: true + '@rspack/dev-server@1.1.4': + resolution: {integrity: sha512-kGHYX2jYf3ZiHwVl0aUEPBOBEIG1aWleCDCAi+Jg32KUu3qr/zDUpCEd0wPuHfLEgk0X0xAEYCS6JMO7nBStNQ==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': '*' + '@rspack/lite-tapable@1.1.0': resolution: {integrity: sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==} @@ -2812,9 +3015,18 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/body-parser@1.19.6': + resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} + + '@types/bonjour@3.5.13': + resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} + '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/connect-history-api-fallback@1.5.4': + resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} + '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} @@ -2845,12 +3057,24 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/express-serve-static-core@4.19.7': + resolution: {integrity: sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==} + + '@types/express@4.17.25': + resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} + '@types/fs-extra@11.0.4': resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@types/http-errors@2.0.5': + resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} + + '@types/http-proxy@1.17.17': + resolution: {integrity: sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==} + '@types/is-url@1.2.32': resolution: {integrity: sha512-46VLdbWI8Sc+hPexQ6NLNR2YpoDyDZIpASHkJQ2Yr+Kf9Giw6LdCTkwOdsnHKPQeh7xTjTmSnxbE8qpxYuCiHA==} @@ -2887,12 +3111,18 @@ packages: '@types/mdx@2.0.13': resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/mocha@10.0.10': resolution: {integrity: sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==} '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node-forge@1.3.14': + resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==} + '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} @@ -2914,6 +3144,12 @@ packages: '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} + '@types/qs@6.14.0': + resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/react-dom@18.3.7': resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} peerDependencies: @@ -2930,12 +3166,33 @@ packages: '@types/react@19.2.7': resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==} + '@types/retry@0.12.2': + resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} + '@types/sarif@2.1.7': resolution: {integrity: sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==} + '@types/semver@7.5.8': + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + + '@types/send@0.17.6': + resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} + + '@types/send@1.2.1': + resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} + + '@types/serve-index@1.9.4': + resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} + + '@types/serve-static@1.15.10': + resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} + '@types/sinonjs__fake-timers@8.1.5': resolution: {integrity: sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==} + '@types/sockjs@0.3.36': + resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} + '@types/source-map-support@0.5.10': resolution: {integrity: sha512-tgVP2H469x9zq34Z0m/fgPewGhg/MLClalNOiPIzQlXrSS2YrKu/xCdSCKnEDwkFha51VKEKB6A9wW26/ZNwzA==} @@ -3172,6 +3429,9 @@ packages: resolution: {integrity: sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==} engines: {node: '>=18.12.0'} + '@zeit/schemas@2.36.0': + resolution: {integrity: sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==} + '@zkochan/js-yaml@0.0.7': resolution: {integrity: sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==} hasBin: true @@ -3213,6 +3473,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + adm-zip@0.5.16: + resolution: {integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==} + engines: {node: '>=12.0'} + agent-base@7.1.3: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} @@ -3255,6 +3519,9 @@ packages: resolution: {integrity: sha512-y7gau/ZOQDqoInTQp0IwTOjkrHc4Aq4R8JgpmCleFwiLl+PbN2DMWoDUWZnrK8AhNJwT++dn28Bt4NZYNLAmuA==} engines: {node: '>= 14.0.0'} + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -3263,6 +3530,11 @@ packages: resolution: {integrity: sha512-YdhtCd19sKRKfAAUsrcC1wzm4JuzJoiX4pOJqIoW2qmKj5WzG/dL8uUJ0361zaXtHqK7gEhOwtAtz7t3Yq3X5g==} engines: {node: '>=18'} + ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -3293,6 +3565,12 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + arch@2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -3302,6 +3580,9 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -3327,6 +3608,10 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -3357,6 +3642,9 @@ packages: resolution: {integrity: sha512-UYmTpOBwgPScZpS4A+YbapwWuBwasxvO/2IOHArSsAhL/+ZdmATBXTex3t+l2hXwLVYK382ibr/nKoY9GKe86w==} hasBin: true + batch@0.6.1: + resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} + better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} @@ -3384,15 +3672,26 @@ packages: bn.js@5.2.2: resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} + body-parser@1.20.4: + resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + body-scroll-lock@4.0.0-beta.0: resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==} + bonjour-service@1.3.0: + resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} boundary@2.0.0: resolution: {integrity: sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==} + boxen@7.0.0: + resolution: {integrity: sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==} + engines: {node: '>=14.16'} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -3440,6 +3739,11 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + btoa@1.2.1: + resolution: {integrity: sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==} + engines: {node: '>= 0.4.0'} + hasBin: true + buffer-builder@0.2.0: resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==} @@ -3468,6 +3772,14 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} + bytes@3.0.0: + resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} + engines: {node: '>= 0.8'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + c8@10.1.3: resolution: {integrity: sha512-LvcyrOAaOnrrlMpW22n690PUvxiq4Uf9WMhQwNJ9vgagkL/ph1+D4uvjvDA5XCbykrc0sx+ay6pVi9YZ1GnhyA==} engines: {node: '>=18'} @@ -3502,6 +3814,10 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} + camelcase@7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + caniuse-lite@1.0.30001751: resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} @@ -3512,10 +3828,22 @@ packages: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} + chalk-template@0.4.0: + resolution: {integrity: sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==} + engines: {node: '>=12'} + + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chalk@5.0.1: + resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chalk@5.4.1: resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} @@ -3584,6 +3912,10 @@ packages: classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -3600,6 +3932,10 @@ packages: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} + clipboardy@3.0.0: + resolution: {integrity: sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -3626,6 +3962,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + colorjs.io@0.5.2: resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==} @@ -3640,6 +3979,10 @@ packages: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + commander@12.1.0: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} @@ -3659,24 +4002,60 @@ packages: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression@1.7.4: + resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} + engines: {node: '>= 0.8.0'} + + compression@1.8.1: + resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==} + engines: {node: '>= 0.8.0'} + compute-scroll-into-view@3.1.1: resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==} concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + concurrently@8.2.2: + resolution: {integrity: sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==} + engines: {node: ^14.13.0 || >=16.0.0} + hasBin: true + config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + console-browserify@1.2.0: resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} constants-browserify@1.0.0: resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} + content-disposition@0.5.2: + resolution: {integrity: sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==} + engines: {node: '>= 0.6'} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie-signature@1.0.7: + resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + cookie@0.7.2: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} @@ -3685,6 +4064,10 @@ packages: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} + cookies@0.9.1: + resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==} + engines: {node: '>= 0.8'} + copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} @@ -3719,6 +4102,10 @@ packages: create-hmac@1.1.7: resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + cron-parser@4.9.0: + resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} + engines: {node: '>=12.0.0'} + cross-env@10.1.0: resolution: {integrity: sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==} engines: {node: '>=20'} @@ -3768,9 +4155,28 @@ packages: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} + date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} + engines: {node: '>=0.11'} + + date-format@4.0.14: + resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==} + engines: {node: '>=4.0'} + dayjs@1.11.19: resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} + debounce@1.2.1: + resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.3.7: resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} engines: {node: '>=6.0'} @@ -3811,6 +4217,9 @@ packages: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} + deep-equal@1.0.1: + resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==} + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -3850,6 +4259,17 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + + depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -3857,6 +4277,10 @@ packages: des.js@1.1.0: resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + detect-indent@6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} @@ -3878,6 +4302,9 @@ packages: resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -3896,6 +4323,10 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} + dns-packet@5.6.1: + resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} + engines: {node: '>=6'} + dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} @@ -3934,6 +4365,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -3952,6 +4386,9 @@ packages: engines: {node: '>=14'} hasBin: true + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + electron-to-chromium@1.5.237: resolution: {integrity: sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==} @@ -3971,9 +4408,16 @@ packages: resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} engines: {node: '>= 4'} + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + encoding-sniffer@0.2.1: resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} @@ -4064,6 +4508,9 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} @@ -4125,10 +4572,17 @@ packages: estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -4144,14 +4598,26 @@ packages: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} + exit-hook@4.0.0: + resolution: {integrity: sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==} + engines: {node: '>=18'} + expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} + expand-tilde@2.0.2: + resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} + engines: {node: '>=0.10.0'} + expect@30.0.5: resolution: {integrity: sha512-P0te2pt+hHI5qLJkIR+iMvS+lYUZml8rKKsohVHAGY+uClp9XVbdyYNJOIjSRpHVp8s8YqxJCiHUkSYZGr8rtQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + express@4.22.1: + resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} + engines: {node: '>= 0.10.0'} + extend-shallow@2.0.1: resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} engines: {node: '>=0.10.0'} @@ -4172,9 +4638,16 @@ packages: fast-uri@3.0.6: resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + fast-url-parser@1.1.3: + resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==} + fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} + fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} @@ -4199,6 +4672,18 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + finalhandler@1.3.2: + resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} + engines: {node: '>= 0.8'} + + find-file-up@2.0.1: + resolution: {integrity: sha512-qVdaUhYO39zmh28/JLQM5CoYN9byEOKEH4qfa8K1eNV17W0UUMJ9WgbR/hHFH+t5rcl+6RTb5UC7ck/I+uRkpQ==} + engines: {node: '>=8'} + + find-pkg@2.0.0: + resolution: {integrity: sha512-WgZ+nKbELDa6N3i/9nrHeNznm+lY3z4YfhDDWgW+5P0pdmMj26bxaxU11ookgY3NyP9GC7HvZ9etp0jRFqGEeQ==} + engines: {node: '>=8'} + find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -4214,6 +4699,9 @@ packages: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + flexsearch@0.8.212: resolution: {integrity: sha512-wSyJr1GUWoOOIISRu+X2IXiOcVfg9qqBRyCPRUdLMIGJqPzMo+jMRlvE83t14v1j0dRMEaBbER/adQjp6Du2pw==} @@ -4238,6 +4726,10 @@ packages: resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} engines: {node: '>= 6'} + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + framer-motion@12.23.26: resolution: {integrity: sha512-cPcIhgR42xBn1Uj+PzOyheMtZ73H927+uWPDVhUMqxy8UHt6Okavb6xIz9J/phFUHUj0OncR6UvMfJTXoc/LKA==} peerDependencies: @@ -4252,6 +4744,10 @@ packages: react-dom: optional: true + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + front-matter@4.0.2: resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} @@ -4270,6 +4766,10 @@ packages: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -4319,6 +4819,9 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} + get-them-args@1.3.2: + resolution: {integrity: sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw==} + git-hooks-list@4.1.1: resolution: {integrity: sha512-cmP497iLq54AZnv4YRAEMnEyQ1eIn4tGKbmswqwmFV4GBnAqE8NLtWxxdXa++AalfgL5EBH4IxTPyquEuGY/jA==} @@ -4350,6 +4853,14 @@ packages: engines: {node: 20 || >=22} hasBin: true + global-modules@1.0.0: + resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==} + engines: {node: '>=0.10.0'} + + global-prefix@1.0.2: + resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} + engines: {node: '>=0.10.0'} + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -4376,6 +4887,13 @@ packages: resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} engines: {node: '>=6.0'} + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + + handle-thing@2.0.1: + resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + happy-dom@20.0.11: resolution: {integrity: sha512-QsCdAUHAmiDeKeaNojb1OHOPF7NjcWPBR7obdu3NwH2a/oyQaLg5d0aaCy/9My6CdPChYF07dvz5chaXBGaD4g==} engines: {node: '>=20.0.0'} @@ -4457,6 +4975,10 @@ packages: hmac-drbg@1.0.1: resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + homedir-polyfill@1.0.3: + resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} + engines: {node: '>=0.10.0'} + hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} @@ -4468,6 +4990,9 @@ packages: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} + hpack.js@2.1.6: + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} + html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} @@ -4491,10 +5016,45 @@ packages: htmlparser2@8.0.2: resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + http-assert@1.5.0: + resolution: {integrity: sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==} + engines: {node: '>= 0.8'} + + http-deceiver@1.2.7: + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} + + http-errors@1.6.3: + resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} + engines: {node: '>= 0.6'} + + http-errors@1.8.1: + resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} + engines: {node: '>= 0.6'} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + http-parser-js@0.5.10: + resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} + http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} + http-proxy-middleware@2.0.9: + resolution: {integrity: sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + + http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + https-browserify@1.0.0: resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} @@ -4514,6 +5074,10 @@ packages: resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} engines: {node: '>=10.18'} + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -4555,6 +5119,9 @@ packages: resolution: {integrity: sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==} engines: {node: '>=18'} + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -4564,6 +5131,14 @@ packages: inline-style-parser@0.2.4: resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + ipaddr.js@2.3.0: + resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==} + engines: {node: '>= 10'} + is-absolute-url@4.0.1: resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4654,6 +5229,10 @@ packages: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} + is-network-error@1.3.0: + resolution: {integrity: sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==} + engines: {node: '>=16'} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -4666,6 +5245,10 @@ packages: resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} engines: {node: '>=8'} + is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + is-plain-obj@4.1.0: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} @@ -4674,6 +5257,10 @@ packages: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} + is-port-reachable@4.0.0: + resolution: {integrity: sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} @@ -4737,6 +5324,11 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} + isomorphic-ws@5.0.0: + resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} + peerDependencies: + ws: '*' + istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -4804,6 +5396,10 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true @@ -4887,13 +5483,32 @@ packages: jws@3.2.2: resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + keygrip@1.1.0: + resolution: {integrity: sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==} + engines: {node: '>= 0.6'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + keytar@7.9.0: resolution: {integrity: sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==} + kill-port@2.0.1: + resolution: {integrity: sha512-e0SVOV5jFo0mx8r7bS29maVWp17qGqLBZ5ricNSajON6//kmb7qqqNnml4twNE8Dtj97UQD+gNFOaipS/q1zzQ==} + hasBin: true + kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} + koa-compose@4.1.0: + resolution: {integrity: sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==} + + koa@3.0.3: + resolution: {integrity: sha512-MeuwbCoN1daWS32/Ni5qkzmrOtQO2qrnfdxDHjrm6s4b59yG4nexAJ0pTEFyzjLp0pBVO80CZp0vW8Ze30Ebow==} + engines: {node: '>= 18'} + + launch-editor@2.12.0: + resolution: {integrity: sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==} + leac@0.6.0: resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} @@ -5015,6 +5630,9 @@ packages: lodash-es@4.17.22: resolution: {integrity: sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==} + lodash.clonedeepwith@4.5.0: + resolution: {integrity: sha512-QRBRSxhbtsX1nc0baxSkkK5WlVTTm/s48DSukcGcWZwIyI8Zz+lB+kFiELJXtzfH4Aj6kMWQ1VWW4U5uUDgZMA==} + lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} @@ -5053,6 +5671,13 @@ packages: resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} engines: {node: '>=18'} + log4js@6.9.1: + resolution: {integrity: sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==} + engines: {node: '>=8.0'} + + long-timeout@0.1.1: + resolution: {integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==} + longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -5085,6 +5710,10 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc + luxon@3.7.2: + resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} + engines: {node: '>=12'} + lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -5176,12 +5805,23 @@ packages: mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + medium-zoom@1.1.0: resolution: {integrity: sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ==} memfs@4.51.1: resolution: {integrity: sha512-Eyt3XrufitN2ZL9c/uIRMyDwXanLI88h/L3MoWqNY747ha3dMR9dWqp8cRT5ntjZ0U1TNuq4U91ZXK0sMBjYOQ==} + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -5189,6 +5829,10 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} @@ -5302,14 +5946,30 @@ packages: resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} hasBin: true + mime-db@1.33.0: + resolution: {integrity: sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==} + engines: {node: '>= 0.6'} + mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.18: + resolution: {integrity: sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==} + engines: {node: '>= 0.6'} + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} @@ -5385,9 +6045,16 @@ packages: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + multicast-dns@7.2.5: + resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} + hasBin: true + mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} @@ -5413,6 +6080,10 @@ packages: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} @@ -5429,6 +6100,19 @@ packages: node-addon-api@7.1.1: resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-forge@1.3.3: + resolution: {integrity: sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==} + engines: {node: '>= 6.13.0'} + node-machine-id@1.1.12: resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==} @@ -5439,6 +6123,10 @@ packages: resolution: {integrity: sha512-kVIOdynrF2CRodHZeP/97Rh1syTUHBNiw17hUCIVhlhEsWlfJm19MuO56s4MdKbr22xWx6mzMnNAgXzVlIYM9Q==} engines: {node: '>=18'} + node-schedule@2.1.1: + resolution: {integrity: sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==} + engines: {node: '>=6'} + nopt@7.2.1: resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -5497,6 +6185,21 @@ packages: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} + obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + + on-headers@1.1.0: + resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} + engines: {node: '>= 0.8'} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -5526,6 +6229,10 @@ packages: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} + opener@1.5.2: + resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} + hasBin: true + ora@5.3.0: resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} engines: {node: '>=10'} @@ -5573,6 +6280,10 @@ packages: resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} engines: {node: '>=18'} + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + engines: {node: '>=16.17'} + p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -5605,6 +6316,10 @@ packages: resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==} engines: {node: '>=18'} + parse-passwd@1.0.0: + resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} + engines: {node: '>=0.10.0'} + parse-semver@1.1.1: resolution: {integrity: sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==} @@ -5620,6 +6335,10 @@ packages: parseley@0.12.1: resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==} + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} @@ -5627,6 +6346,9 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-is-inside@1.0.2: + resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -5645,6 +6367,12 @@ packages: path-serializer@0.5.1: resolution: {integrity: sha512-bMTznw/TiZbmxlPQEV1pFatJFQcBKt3i9glDcPqygSx5xGrcM4MTCSjY+3SgW9Y628zfRmuJ1uAc/t/A3Tw0QA==} + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + + path-to-regexp@2.2.1: + resolution: {integrity: sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -5773,6 +6501,10 @@ packages: proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -5810,12 +6542,27 @@ packages: r-json@1.3.1: resolution: {integrity: sha512-5nhRFfjVMQdrwKUfUlRpDUCocdKtjSnYZ1R/86mpZDV3MfsZ3dYYNjSGuMX+mPBvFvQBhdzxSqxkuLPLv4uFGg==} + rambda@9.4.2: + resolution: {integrity: sha512-++euMfxnl7OgaEKwXh9QqThOjMeta2HH001N1v4mYQzBjJBnmXBh2BCK6dZAbICFVXOFUVD3xFG0R3ZPU0mxXw==} + randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} randomfill@1.0.4: resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + range-parser@1.2.0: + resolution: {integrity: sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==} + engines: {node: '>= 0.6'} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.3: + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + engines: {node: '>= 0.8'} + rc-cascader@3.34.0: resolution: {integrity: sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag==} peerDependencies: @@ -6051,6 +6798,11 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true + react-dom@17.0.2: + resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} + peerDependencies: + react: 17.0.2 + react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: @@ -6110,6 +6862,10 @@ packages: react-dom: optional: true + react@17.0.2: + resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==} + engines: {node: '>=0.10.0'} + react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -6183,6 +6939,13 @@ packages: regex@6.0.1: resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==} + registry-auth-token@3.3.2: + resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==} + + registry-url@3.1.0: + resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==} + engines: {node: '>=0.10.0'} + rehype-external-links@3.0.0: resolution: {integrity: sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==} @@ -6215,9 +6978,16 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + resize-observer-polyfill@1.5.1: resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + resolve-dir@1.0.1: + resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} + engines: {node: '>=0.10.0'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -6235,6 +7005,10 @@ packages: engines: {node: '>= 0.4'} hasBin: true + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} @@ -6243,10 +7017,17 @@ packages: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + ripemd160@2.0.3: resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} engines: {node: '>= 0.8'} @@ -6453,6 +7234,9 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} + scheduler@0.20.2: + resolution: {integrity: sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==} + scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} @@ -6478,6 +7262,13 @@ packages: selderee@0.11.0: resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==} + select-hose@2.0.0: + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} + + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true @@ -6491,14 +7282,39 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + semver@7.7.3: resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true + send@0.19.2: + resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} + engines: {node: '>= 0.8.0'} + serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + serve-handler@6.1.5: + resolution: {integrity: sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==} + + serve-index@1.9.1: + resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} + engines: {node: '>= 0.8.0'} + + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} + engines: {node: '>= 0.8.0'} + + serve@14.2.3: + resolution: {integrity: sha512-VqUFMC7K3LDGeGnJM9h56D3XGKb6KGgOw0cVNtA26yYXHCcpxf3xwCTUaQoWlVS7i8Jdh3GjQkOB23qsXyjoyQ==} + engines: {node: '>= 14'} + hasBin: true + set-cookie-parser@2.7.2: resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} @@ -6513,6 +7329,12 @@ packages: setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + setprototypeof@1.1.0: + resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + sha.js@2.4.12: resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==} engines: {node: '>= 0.10'} @@ -6526,6 +7348,13 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shell-exec@1.0.2: + resolution: {integrity: sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==} + + shell-quote@1.8.3: + resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} + engines: {node: '>= 0.4'} + shiki@3.20.0: resolution: {integrity: sha512-kgCOlsnyWb+p0WU+01RjkCH+eBVsjL1jOwUYWv0YDWkM2/A46+LDKVs5yZCUXjJG6bj4ndFoAg5iLIIue6dulg==} @@ -6596,6 +7425,9 @@ packages: resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} engines: {node: '>=10.2.0'} + sockjs@0.3.24: + resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + sort-object-keys@2.0.1: resolution: {integrity: sha512-R89fO+z3x7hiKPXX5P0qim+ge6Y60AjtlW+QQpRozrrNcR1lw9Pkpm5MLB56HoNvdcLHL4wbpq16OcvGpEDJIg==} @@ -6604,6 +7436,9 @@ packages: engines: {node: '>=20'} hasBin: true + sorted-array-functions@1.3.0: + resolution: {integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -6622,6 +7457,9 @@ packages: space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + spawn-command@0.0.2: + resolution: {integrity: sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==} + spawndamnit@3.0.1: resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} @@ -6640,6 +7478,13 @@ packages: spdx-license-ids@3.0.22: resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + spdy-transport@3.0.0: + resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} + + spdy@4.0.2: + resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} + engines: {node: '>=6.0.0'} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -6657,6 +7502,14 @@ packages: resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} engines: {node: '>=6'} + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} @@ -6670,6 +7523,10 @@ packages: stream-http@3.2.0: resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==} + streamroller@3.1.5: + resolution: {integrity: sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==} + engines: {node: '>=8.0'} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -6869,6 +7726,9 @@ packages: resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} engines: {node: '>=18'} + thunky@1.1.0: + resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + timers-browserify@2.0.12: resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} engines: {node: '>=0.6.0'} @@ -6915,6 +7775,10 @@ packages: toggle-selection@1.0.6: resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -6923,6 +7787,9 @@ packages: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@5.1.1: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} @@ -6960,6 +7827,10 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsscmp@1.0.6: + resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} + engines: {node: '>=0.6.x'} + tty-browserify@0.0.1: resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} @@ -6990,6 +7861,14 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + type-is@2.0.1: + resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} + engines: {node: '>= 0.6'} + typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -7063,6 +7942,10 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + upath@2.0.1: resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} engines: {node: '>=4'} @@ -7073,6 +7956,9 @@ packages: peerDependencies: browserslist: '>= 4.21.0' + update-check@1.5.4: + resolution: {integrity: sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==} + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -7098,6 +7984,10 @@ packages: util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -7165,16 +8055,49 @@ packages: resolution: {integrity: sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==} engines: {node: '>=10.13.0'} + wbuf@1.7.3: + resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} + webpack-bundle-analyzer@4.10.2: + resolution: {integrity: sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==} + engines: {node: '>= 10.13.0'} + hasBin: true + + webpack-dev-middleware@7.4.5: + resolution: {integrity: sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + + webpack-dev-server@5.2.2: + resolution: {integrity: sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==} + engines: {node: '>= 18.12.0'} + hasBin: true + peerDependencies: + webpack: ^5.0.0 + webpack-cli: '*' + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + webpack-license-plugin@4.5.1: resolution: {integrity: sha512-WbjMSMPHzFePCSQJqP0qFskGPSwdf3JxIoXa1SK3d1hCXQee7KUrIb+riyXUId71kcHOSyE12pTyrhMl1ozszA==} engines: {node: '>=16.0.0'} @@ -7195,6 +8118,14 @@ packages: webpack-cli: optional: true + websocket-driver@0.7.4: + resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + engines: {node: '>=0.8.0'} + + websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} @@ -7212,15 +8143,26 @@ packages: resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which-typed-array@1.1.19: resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} engines: {node: '>= 0.4'} + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true + widest-line@4.0.1: + resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} + engines: {node: '>=12'} + workerpool@9.3.3: resolution: {integrity: sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==} @@ -7235,6 +8177,18 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + ws@8.17.1: resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} engines: {node: '>=10.0.0'} @@ -7247,6 +8201,18 @@ packages: utf-8-validate: optional: true + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + ws@8.18.3: resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} engines: {node: '>=10.0.0'} @@ -7672,6 +8638,26 @@ snapshots: '@babel/compat-data@7.28.0': {} + '@babel/core@7.24.7': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.24.7) + '@babel/helpers': 7.28.3 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.5 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/core@7.28.3': dependencies: '@ampproject/remapping': 2.3.0 @@ -7741,6 +8727,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.28.3(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.3 + transitivePeerDependencies: + - supports-color + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.3)': dependencies: '@babel/core': 7.28.3 @@ -7801,6 +8796,11 @@ snapshots: '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.3)': dependencies: '@babel/core': 7.28.3 @@ -8079,6 +9079,8 @@ snapshots: '@csstools/css-tokenizer@3.0.4': {} + '@discoveryjs/json-ext@0.5.7': {} + '@docsearch/core@4.4.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': optionalDependencies: '@types/react': 19.2.7 @@ -8234,6 +9236,8 @@ snapshots: '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) tslib: 2.8.1 + '@leichtgewicht/ip-codec@2.0.5': {} + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.26.9 @@ -8322,47 +9326,200 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} - '@module-federation/error-codes@0.21.6': {} - - '@module-federation/error-codes@0.22.0': {} - - '@module-federation/runtime-core@0.21.6': - dependencies: - '@module-federation/error-codes': 0.21.6 - '@module-federation/sdk': 0.21.6 - - '@module-federation/runtime-core@0.22.0': + '@module-federation/bridge-react-webpack-plugin@0.22.0': dependencies: - '@module-federation/error-codes': 0.22.0 '@module-federation/sdk': 0.22.0 + '@types/semver': 7.5.8 + semver: 7.6.3 - '@module-federation/runtime-tools@0.21.6': + '@module-federation/cli@0.22.0(typescript@5.9.3)': dependencies: - '@module-federation/runtime': 0.21.6 - '@module-federation/webpack-bundler-runtime': 0.21.6 + '@module-federation/dts-plugin': 0.22.0(typescript@5.9.3) + '@module-federation/sdk': 0.22.0 + chalk: 3.0.0 + commander: 11.1.0 + jiti: 2.4.2 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - typescript + - utf-8-validate + - vue-tsc - '@module-federation/runtime-tools@0.22.0': + '@module-federation/data-prefetch@0.22.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@module-federation/runtime': 0.22.0 - '@module-federation/webpack-bundler-runtime': 0.22.0 + '@module-federation/sdk': 0.22.0 + fs-extra: 9.1.0 + react: 17.0.2 + react-dom: 17.0.2(react@17.0.2) - '@module-federation/runtime@0.21.6': + '@module-federation/dts-plugin@0.22.0(typescript@5.9.3)': dependencies: - '@module-federation/error-codes': 0.21.6 - '@module-federation/runtime-core': 0.21.6 - '@module-federation/sdk': 0.21.6 + '@module-federation/error-codes': 0.22.0 + '@module-federation/managers': 0.22.0 + '@module-federation/sdk': 0.22.0 + '@module-federation/third-party-dts-extractor': 0.22.0 + adm-zip: 0.5.16 + ansi-colors: 4.1.3 + axios: 1.13.2 + chalk: 3.0.0 + fs-extra: 9.1.0 + isomorphic-ws: 5.0.0(ws@8.18.0) + koa: 3.0.3 + lodash.clonedeepwith: 4.5.0 + log4js: 6.9.1 + node-schedule: 2.1.1 + rambda: 9.4.2 + typescript: 5.9.3 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate - '@module-federation/runtime@0.22.0': + '@module-federation/enhanced@0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)))': dependencies: + '@module-federation/bridge-react-webpack-plugin': 0.22.0 + '@module-federation/cli': 0.22.0(typescript@5.9.3) + '@module-federation/data-prefetch': 0.22.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@module-federation/dts-plugin': 0.22.0(typescript@5.9.3) '@module-federation/error-codes': 0.22.0 - '@module-federation/runtime-core': 0.22.0 + '@module-federation/inject-external-runtime-core-plugin': 0.22.0(@module-federation/runtime-tools@0.22.0) + '@module-federation/managers': 0.22.0 + '@module-federation/manifest': 0.22.0(typescript@5.9.3) + '@module-federation/rspack': 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(typescript@5.9.3) + '@module-federation/runtime-tools': 0.22.0 '@module-federation/sdk': 0.22.0 + btoa: 1.2.1 + schema-utils: 4.3.3 + upath: 2.0.1 + optionalDependencies: + typescript: 5.9.3 + webpack: 5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)) + transitivePeerDependencies: + - '@rspack/core' + - bufferutil + - debug + - react + - react-dom + - supports-color + - utf-8-validate - '@module-federation/sdk@0.21.6': {} + '@module-federation/error-codes@0.21.6': {} - '@module-federation/sdk@0.22.0': {} + '@module-federation/error-codes@0.22.0': {} - '@module-federation/webpack-bundler-runtime@0.21.6': + '@module-federation/inject-external-runtime-core-plugin@0.22.0(@module-federation/runtime-tools@0.22.0)': + dependencies: + '@module-federation/runtime-tools': 0.22.0 + + '@module-federation/managers@0.22.0': + dependencies: + '@module-federation/sdk': 0.22.0 + find-pkg: 2.0.0 + fs-extra: 9.1.0 + + '@module-federation/manifest@0.22.0(typescript@5.9.3)': + dependencies: + '@module-federation/dts-plugin': 0.22.0(typescript@5.9.3) + '@module-federation/managers': 0.22.0 + '@module-federation/sdk': 0.22.0 + chalk: 3.0.0 + find-pkg: 2.0.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - typescript + - utf-8-validate + - vue-tsc + + '@module-federation/node@2.7.26(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)))': + dependencies: + '@module-federation/enhanced': 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@module-federation/runtime': 0.22.0 + '@module-federation/sdk': 0.22.0 + btoa: 1.2.1 + encoding: 0.1.13 + node-fetch: 2.7.0(encoding@0.1.13) + webpack: 5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)) + optionalDependencies: + react: 17.0.2 + react-dom: 17.0.2(react@17.0.2) + transitivePeerDependencies: + - '@rspack/core' + - bufferutil + - debug + - supports-color + - typescript + - utf-8-validate + - vue-tsc + + '@module-federation/rspack@0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(typescript@5.9.3)': + dependencies: + '@module-federation/bridge-react-webpack-plugin': 0.22.0 + '@module-federation/dts-plugin': 0.22.0(typescript@5.9.3) + '@module-federation/inject-external-runtime-core-plugin': 0.22.0(@module-federation/runtime-tools@0.22.0) + '@module-federation/managers': 0.22.0 + '@module-federation/manifest': 0.22.0(typescript@5.9.3) + '@module-federation/runtime-tools': 0.22.0 + '@module-federation/sdk': 0.22.0 + '@rspack/core': 1.6.8(@swc/helpers@0.5.18) + btoa: 1.2.1 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + '@module-federation/runtime-core@0.21.6': + dependencies: + '@module-federation/error-codes': 0.21.6 + '@module-federation/sdk': 0.21.6 + + '@module-federation/runtime-core@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@module-federation/runtime-tools@0.21.6': + dependencies: + '@module-federation/runtime': 0.21.6 + '@module-federation/webpack-bundler-runtime': 0.21.6 + + '@module-federation/runtime-tools@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/webpack-bundler-runtime': 0.22.0 + + '@module-federation/runtime@0.21.6': + dependencies: + '@module-federation/error-codes': 0.21.6 + '@module-federation/runtime-core': 0.21.6 + '@module-federation/sdk': 0.21.6 + + '@module-federation/runtime@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/runtime-core': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@module-federation/sdk@0.21.6': {} + + '@module-federation/sdk@0.22.0': {} + + '@module-federation/third-party-dts-extractor@0.22.0': + dependencies: + find-pkg: 2.0.0 + fs-extra: 9.1.0 + resolve: 1.22.8 + + '@module-federation/webpack-bundler-runtime@0.21.6': dependencies: '@module-federation/runtime': 0.21.6 '@module-federation/sdk': 0.21.6 @@ -8565,6 +9722,10 @@ snapshots: '@pkgr/core@0.2.9': {} + '@playwright/test@1.57.0': + dependencies: + playwright: 1.57.0 + '@polka/url@1.0.0-next.29': {} '@rc-component/async-validator@5.0.4': @@ -8992,6 +10153,22 @@ snapshots: '@rspack/binding-win32-ia32-msvc': 1.7.0 '@rspack/binding-win32-x64-msvc': 1.7.0 + '@rspack/cli@1.6.8(@rspack/core@1.6.8(@swc/helpers@0.5.18))(@types/express@4.17.25)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)))': + dependencies: + '@discoveryjs/json-ext': 0.5.7 + '@rspack/core': 1.6.8(@swc/helpers@0.5.18) + '@rspack/dev-server': 1.1.4(@rspack/core@1.6.8(@swc/helpers@0.5.18))(@types/express@4.17.25)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + exit-hook: 4.0.0 + webpack-bundle-analyzer: 4.10.2 + transitivePeerDependencies: + - '@types/express' + - bufferutil + - debug + - supports-color + - utf-8-validate + - webpack + - webpack-cli + '@rspack/core@1.6.8(@swc/helpers@0.5.18)': dependencies: '@module-federation/runtime-tools': 0.21.6 @@ -9008,6 +10185,23 @@ snapshots: optionalDependencies: '@swc/helpers': 0.5.18 + '@rspack/dev-server@1.1.4(@rspack/core@1.6.8(@swc/helpers@0.5.18))(@types/express@4.17.25)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)))': + dependencies: + '@rspack/core': 1.6.8(@swc/helpers@0.5.18) + chokidar: 3.6.0 + http-proxy-middleware: 2.0.9(@types/express@4.17.25) + p-retry: 6.2.1 + webpack-dev-server: 5.2.2(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + ws: 8.18.3 + transitivePeerDependencies: + - '@types/express' + - bufferutil + - debug + - supports-color + - utf-8-validate + - webpack + - webpack-cli + '@rspack/lite-tapable@1.1.0': {} '@rspack/plugin-react-refresh@1.5.2(react-refresh@0.18.0)': @@ -9324,54 +10518,54 @@ snapshots: '@standard-schema/spec@1.0.0': {} - '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.3)': + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.28.3 + '@babel/core': 7.24.7 - '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.28.3)': + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.28.3 + '@babel/core': 7.24.7 - '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.28.3)': + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.28.3 + '@babel/core': 7.24.7 - '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.28.3)': + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.28.3 + '@babel/core': 7.24.7 - '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.28.3)': + '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.28.3 + '@babel/core': 7.24.7 - '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.28.3)': + '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.28.3 + '@babel/core': 7.24.7 - '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.28.3)': + '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.28.3 + '@babel/core': 7.24.7 - '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.28.3)': + '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.28.3 + '@babel/core': 7.24.7 - '@svgr/babel-preset@8.1.0(@babel/core@7.28.3)': + '@svgr/babel-preset@8.1.0(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.28.3 - '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.28.3) - '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.28.3) - '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.28.3) - '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.28.3) - '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.28.3) - '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.28.3) - '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.28.3) - '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.28.3) + '@babel/core': 7.24.7 + '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.24.7) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.24.7) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.24.7) + '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.24.7) + '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.24.7) + '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.24.7) + '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.24.7) + '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.24.7) '@svgr/core@8.1.0(typescript@5.9.3)': dependencies: - '@babel/core': 7.28.3 - '@svgr/babel-preset': 8.1.0(@babel/core@7.28.3) + '@babel/core': 7.24.7 + '@svgr/babel-preset': 8.1.0(@babel/core@7.24.7) camelcase: 6.3.0 cosmiconfig: 8.3.6(typescript@5.9.3) snake-case: 3.0.4 @@ -9386,8 +10580,8 @@ snapshots: '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.9.3))': dependencies: - '@babel/core': 7.28.3 - '@svgr/babel-preset': 8.1.0(@babel/core@7.28.3) + '@babel/core': 7.24.7 + '@svgr/babel-preset': 8.1.0(@babel/core@7.24.7) '@svgr/core': 8.1.0(typescript@5.9.3) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 @@ -9640,11 +10834,25 @@ snapshots: dependencies: '@babel/types': 7.28.5 + '@types/body-parser@1.19.6': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 22.18.6 + + '@types/bonjour@3.5.13': + dependencies: + '@types/node': 22.18.6 + '@types/chai@5.2.3': dependencies: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 + '@types/connect-history-api-fallback@1.5.4': + dependencies: + '@types/express-serve-static-core': 4.19.7 + '@types/node': 22.18.6 + '@types/connect@3.4.38': dependencies: '@types/node': 22.18.6 @@ -9679,6 +10887,20 @@ snapshots: '@types/estree@1.0.8': {} + '@types/express-serve-static-core@4.19.7': + dependencies: + '@types/node': 22.18.6 + '@types/qs': 6.14.0 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 + + '@types/express@4.17.25': + dependencies: + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 4.19.7 + '@types/qs': 6.14.0 + '@types/serve-static': 1.15.10 + '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 @@ -9688,6 +10910,12 @@ snapshots: dependencies: '@types/unist': 3.0.3 + '@types/http-errors@2.0.5': {} + + '@types/http-proxy@1.17.17': + dependencies: + '@types/node': 22.18.6 + '@types/is-url@1.2.32': {} '@types/istanbul-lib-coverage@2.0.6': {} @@ -9731,10 +10959,16 @@ snapshots: '@types/mdx@2.0.13': {} + '@types/mime@1.3.5': {} + '@types/mocha@10.0.10': {} '@types/ms@2.1.0': {} + '@types/node-forge@1.3.14': + dependencies: + '@types/node': 22.18.6 + '@types/node@12.20.55': {} '@types/node@20.19.21': @@ -9755,6 +10989,10 @@ snapshots: '@types/prop-types@15.7.15': {} + '@types/qs@6.14.0': {} + + '@types/range-parser@1.2.7': {} + '@types/react-dom@18.3.7(@types/react@18.3.27)': dependencies: '@types/react': 18.3.27 @@ -9772,10 +11010,37 @@ snapshots: dependencies: csstype: 3.2.3 + '@types/retry@0.12.2': {} + '@types/sarif@2.1.7': {} + '@types/semver@7.5.8': {} + + '@types/send@0.17.6': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 22.18.6 + + '@types/send@1.2.1': + dependencies: + '@types/node': 22.18.6 + + '@types/serve-index@1.9.4': + dependencies: + '@types/express': 4.17.25 + + '@types/serve-static@1.15.10': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 22.18.6 + '@types/send': 0.17.6 + '@types/sinonjs__fake-timers@8.1.5': {} + '@types/sockjs@0.3.36': + dependencies: + '@types/node': 22.18.6 + '@types/source-map-support@0.5.10': dependencies: source-map: 0.6.1 @@ -9952,6 +11217,22 @@ snapshots: '@vue/babel-helper-vue-transform-on@1.5.0': {} + '@vue/babel-plugin-jsx@1.5.0(@babel/core@7.24.7)': + dependencies: + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.24.7) + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.5 + '@vue/babel-helper-vue-transform-on': 1.5.0 + '@vue/babel-plugin-resolve-type': 1.5.0(@babel/core@7.24.7) + '@vue/shared': 3.5.26 + optionalDependencies: + '@babel/core': 7.24.7 + transitivePeerDependencies: + - supports-color + '@vue/babel-plugin-jsx@1.5.0(@babel/core@7.28.3)': dependencies: '@babel/helper-module-imports': 7.27.1 @@ -9968,6 +11249,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@vue/babel-plugin-resolve-type@1.5.0(@babel/core@7.24.7)': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/core': 7.24.7 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/parser': 7.28.5 + '@vue/compiler-sfc': 3.5.26 + transitivePeerDependencies: + - supports-color + '@vue/babel-plugin-resolve-type@1.5.0(@babel/core@7.28.3)': dependencies: '@babel/code-frame': 7.27.1 @@ -10128,6 +11420,8 @@ snapshots: js-yaml: 3.14.1 tslib: 2.8.1 + '@zeit/schemas@2.36.0': {} + '@zkochan/js-yaml@0.0.7': dependencies: argparse: 2.0.1 @@ -10161,6 +11455,8 @@ snapshots: acorn@8.15.0: {} + adm-zip@0.5.16: {} + agent-base@7.1.3: {} ai@5.0.76(zod@4.1.12): @@ -10226,12 +11522,18 @@ snapshots: '@algolia/requester-fetch': 5.37.0 '@algolia/requester-node-http': 5.37.0 + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + ansi-colors@4.1.3: {} ansi-escapes@7.1.0: dependencies: environment: 1.1.0 + ansi-html-community@0.0.8: {} + ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -10244,7 +11546,7 @@ snapshots: ansi-styles@6.2.1: {} - antd@5.29.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + antd@5.29.3(date-fns@2.30.0)(luxon@3.7.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: '@ant-design/colors': 7.2.1 '@ant-design/cssinjs': 1.24.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -10276,7 +11578,7 @@ snapshots: rc-motion: 2.9.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) rc-notification: 5.6.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) rc-pagination: 5.1.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - rc-picker: 4.11.3(dayjs@1.11.19)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + rc-picker: 4.11.3(date-fns@2.30.0)(dayjs@1.11.19)(luxon@3.7.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) rc-progress: 4.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) rc-rate: 2.13.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) rc-resize-observer: 1.4.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -10307,6 +11609,10 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + arch@2.2.0: {} + + arg@5.0.2: {} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -10317,6 +11623,8 @@ snapshots: dependencies: dequal: 2.0.3 + array-flatten@1.1.1: {} + array-union@2.1.0: {} asn1.js@4.10.1: @@ -10341,6 +11649,8 @@ snapshots: asynckit@0.4.0: {} + at-least-node@1.0.0: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -10360,8 +11670,8 @@ snapshots: babel-plugin-vue-jsx-hmr@1.0.0: dependencies: - '@babel/core': 7.28.3 - '@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.28.3) + '@babel/core': 7.24.7 + '@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.24.7) transitivePeerDependencies: - supports-color @@ -10375,6 +11685,8 @@ snapshots: baseline-browser-mapping@2.8.18: {} + batch@0.6.1: {} + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 @@ -10399,12 +11711,45 @@ snapshots: bn.js@5.2.2: {} + body-parser@1.20.4: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.14.0 + raw-body: 2.5.3 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + body-scroll-lock@4.0.0-beta.0: {} + bonjour-service@1.3.0: + dependencies: + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + boolbase@1.0.0: {} boundary@2.0.0: {} + boxen@7.0.0: + dependencies: + ansi-align: 3.0.1 + camelcase: 7.0.1 + chalk: 5.4.1 + cli-boxes: 3.0.0 + string-width: 5.1.2 + type-fest: 2.19.0 + widest-line: 4.0.1 + wrap-ansi: 8.1.0 + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -10480,6 +11825,8 @@ snapshots: node-releases: 2.0.25 update-browserslist-db: 1.1.3(browserslist@4.26.3) + btoa@1.2.1: {} + buffer-builder@0.2.0: {} buffer-crc32@0.2.13: {} @@ -10506,6 +11853,10 @@ snapshots: dependencies: run-applescript: 7.1.0 + bytes@3.0.0: {} + + bytes@3.1.2: {} + c8@10.1.3: dependencies: '@bcoe/v8-coverage': 1.0.2 @@ -10543,6 +11894,8 @@ snapshots: camelcase@6.3.0: {} + camelcase@7.0.1: {} + caniuse-lite@1.0.30001751: {} ccount@2.0.1: {} @@ -10555,11 +11908,22 @@ snapshots: loupe: 3.1.4 pathval: 2.0.0 + chalk-template@0.4.0: + dependencies: + chalk: 4.1.2 + + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 + chalk@5.0.1: {} + chalk@5.4.1: {} character-entities-html4@2.1.0: {} @@ -10644,6 +12008,8 @@ snapshots: classnames@2.5.1: {} + cli-boxes@3.0.0: {} + cli-cursor@3.1.0: dependencies: restore-cursor: 3.1.0 @@ -10656,6 +12022,12 @@ snapshots: cli-spinners@2.9.2: {} + clipboardy@3.0.0: + dependencies: + arch: 2.2.0 + execa: 5.1.1 + is-wsl: 2.2.0 + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -10676,6 +12048,8 @@ snapshots: color-name@1.1.4: {} + colorette@2.0.20: {} + colorjs.io@0.5.2: {} combined-stream@1.0.8: @@ -10686,6 +12060,8 @@ snapshots: commander@10.0.1: {} + commander@11.1.0: {} + commander@12.1.0: {} commander@13.1.0: {} @@ -10696,25 +12072,82 @@ snapshots: commander@7.2.0: {} + compressible@2.0.18: + dependencies: + mime-db: 1.54.0 + + compression@1.7.4: + dependencies: + accepts: 1.3.8 + bytes: 3.0.0 + compressible: 2.0.18 + debug: 2.6.9 + on-headers: 1.0.2 + safe-buffer: 5.1.2 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + compression@1.8.1: + dependencies: + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9 + negotiator: 0.6.4 + on-headers: 1.1.0 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + compute-scroll-into-view@3.1.1: {} concat-map@0.0.1: {} + concurrently@8.2.2: + dependencies: + chalk: 4.1.2 + date-fns: 2.30.0 + lodash: 4.17.21 + rxjs: 7.8.2 + shell-quote: 1.8.3 + spawn-command: 0.0.2 + supports-color: 8.1.1 + tree-kill: 1.2.2 + yargs: 17.7.2 + config-chain@1.1.13: dependencies: ini: 1.3.8 proto-list: 1.2.4 + connect-history-api-fallback@2.0.0: {} + console-browserify@1.2.0: {} constants-browserify@1.0.0: {} + content-disposition@0.5.2: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + convert-source-map@2.0.0: {} + cookie-signature@1.0.7: {} + cookie@0.7.2: {} cookie@1.1.1: {} + cookies@0.9.1: + dependencies: + depd: 2.0.0 + keygrip: 1.1.0 + copy-to-clipboard@3.3.3: dependencies: toggle-selection: 1.0.6 @@ -10761,6 +12194,10 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.12 + cron-parser@4.9.0: + dependencies: + luxon: 3.7.2 + cross-env@10.1.0: dependencies: '@epic-web/invariant': 1.0.0 @@ -10827,8 +12264,20 @@ snapshots: whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 + date-fns@2.30.0: + dependencies: + '@babel/runtime': 7.26.9 + + date-format@4.0.14: {} + dayjs@1.11.19: {} + debounce@1.2.1: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + debug@4.3.7: dependencies: ms: 2.1.3 @@ -10858,8 +12307,9 @@ snapshots: deep-eql@5.0.2: {} - deep-extend@0.6.0: - optional: true + deep-equal@1.0.1: {} + + deep-extend@0.6.0: {} deepmerge@4.3.1: {} @@ -10892,6 +12342,12 @@ snapshots: delayed-stream@1.0.0: {} + delegates@1.0.0: {} + + depd@1.1.2: {} + + depd@2.0.0: {} + dequal@2.0.3: {} des.js@1.1.0: @@ -10899,6 +12355,8 @@ snapshots: inherits: 2.0.4 minimalistic-assert: 1.0.1 + destroy@1.2.0: {} + detect-indent@6.1.0: {} detect-indent@7.0.1: {} @@ -10910,6 +12368,8 @@ snapshots: detect-newline@4.0.1: {} + detect-node@2.1.0: {} + devlop@1.1.0: dependencies: dequal: 2.0.3 @@ -10928,6 +12388,10 @@ snapshots: dependencies: path-type: 4.0.0 + dns-packet@5.6.1: + dependencies: + '@leichtgewicht/ip-codec': 2.0.5 + dom-accessibility-api@0.5.16: {} dom-accessibility-api@0.6.3: {} @@ -10969,6 +12433,8 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + duplexer@0.1.2: {} + eastasianwidth@0.2.0: {} ecdsa-sig-formatter@1.0.11: @@ -10994,6 +12460,8 @@ snapshots: minimatch: 9.0.1 semver: 7.7.3 + ee-first@1.1.1: {} + electron-to-chromium@1.5.237: {} elliptic@6.6.1: @@ -11014,11 +12482,17 @@ snapshots: emojis-list@3.0.0: {} + encodeurl@2.0.0: {} + encoding-sniffer@0.2.1: dependencies: iconv-lite: 0.6.3 whatwg-encoding: 3.1.1 + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + end-of-stream@1.4.4: dependencies: once: 1.4.0 @@ -11115,6 +12589,8 @@ snapshots: escalade@3.2.0: {} + escape-html@1.0.3: {} + escape-string-regexp@1.0.5: {} escape-string-regexp@2.0.0: {} @@ -11173,8 +12649,12 @@ snapshots: dependencies: '@types/estree': 1.0.8 + etag@1.8.1: {} + event-target-shim@5.0.1: {} + eventemitter3@4.0.7: {} + events@3.3.0: {} eventsource-parser@3.0.6: {} @@ -11196,9 +12676,15 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + exit-hook@4.0.0: {} + expand-template@2.0.3: optional: true + expand-tilde@2.0.2: + dependencies: + homedir-polyfill: 1.0.3 + expect@30.0.5: dependencies: '@jest/expect-utils': 30.0.5 @@ -11208,6 +12694,42 @@ snapshots: jest-mock: 30.0.5 jest-util: 30.0.5 + express@4.22.1: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.4 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.0.7 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.2 + fresh: 0.5.2 + http-errors: 2.0.1 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.14.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.2 + serve-static: 1.16.3 + setprototypeof: 1.2.0 + statuses: 2.0.2 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + extend-shallow@2.0.1: dependencies: is-extendable: 0.1.1 @@ -11228,10 +12750,18 @@ snapshots: fast-uri@3.0.6: {} + fast-url-parser@1.1.3: + dependencies: + punycode: 1.4.1 + fastq@1.19.1: dependencies: reusify: 1.1.0 + faye-websocket@0.11.4: + dependencies: + websocket-driver: 0.7.4 + fd-slicer@1.1.0: dependencies: pend: 1.2.0 @@ -11250,6 +12780,26 @@ snapshots: dependencies: to-regex-range: 5.0.1 + finalhandler@1.3.2: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-file-up@2.0.1: + dependencies: + resolve-dir: 1.0.1 + + find-pkg@2.0.0: + dependencies: + find-file-up: 2.0.1 + find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -11264,6 +12814,8 @@ snapshots: flat@5.0.2: {} + flatted@3.3.3: {} + flexsearch@0.8.212: {} follow-redirects@1.15.9: {} @@ -11285,6 +12837,8 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + forwarded@0.2.0: {} + framer-motion@12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: motion-dom: 12.23.23 @@ -11294,6 +12848,8 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + fresh@0.5.2: {} + front-matter@4.0.2: dependencies: js-yaml: 3.14.1 @@ -11318,6 +12874,13 @@ snapshots: jsonfile: 4.0.0 universalify: 0.1.2 + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + fsevents@2.3.2: optional: true @@ -11358,6 +12921,8 @@ snapshots: get-stream@6.0.1: {} + get-them-args@1.3.2: {} + git-hooks-list@4.1.1: {} github-from-package@0.0.0: @@ -11393,6 +12958,20 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 2.0.0 + global-modules@1.0.0: + dependencies: + global-prefix: 1.0.2 + is-windows: 1.0.2 + resolve-dir: 1.0.1 + + global-prefix@1.0.2: + dependencies: + expand-tilde: 2.0.2 + homedir-polyfill: 1.0.3 + ini: 1.3.8 + is-windows: 1.0.2 + which: 1.3.1 + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -11429,6 +13008,12 @@ snapshots: section-matter: 1.0.0 strip-bom-string: 1.0.0 + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + + handle-thing@2.0.1: {} + happy-dom@20.0.11: dependencies: '@types/node': 20.19.21 @@ -11598,6 +13183,10 @@ snapshots: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 + homedir-polyfill@1.0.3: + dependencies: + parse-passwd: 1.0.0 + hookable@5.5.3: {} hosted-git-info@4.1.0: @@ -11608,6 +13197,13 @@ snapshots: dependencies: lru-cache: 10.4.3 + hpack.js@2.1.6: + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 @@ -11640,6 +13236,38 @@ snapshots: domutils: 3.2.2 entities: 4.5.0 + http-assert@1.5.0: + dependencies: + deep-equal: 1.0.1 + http-errors: 1.8.1 + + http-deceiver@1.2.7: {} + + http-errors@1.6.3: + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: 1.5.0 + + http-errors@1.8.1: + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 1.5.0 + toidentifier: 1.0.1 + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + http-parser-js@0.5.10: {} + http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 @@ -11647,6 +13275,26 @@ snapshots: transitivePeerDependencies: - supports-color + http-proxy-middleware@2.0.9(@types/express@4.17.25): + dependencies: + '@types/http-proxy': 1.17.17 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.8 + optionalDependencies: + '@types/express': 4.17.25 + transitivePeerDependencies: + - debug + + http-proxy@1.18.1: + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.9 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + https-browserify@1.0.0: {} https-proxy-agent@7.0.6: @@ -11662,6 +13310,10 @@ snapshots: hyperdyperid@1.2.0: {} + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -11691,12 +13343,18 @@ snapshots: index-to-position@1.1.0: {} + inherits@2.0.3: {} + inherits@2.0.4: {} ini@1.3.8: {} inline-style-parser@0.2.4: {} + ipaddr.js@1.9.1: {} + + ipaddr.js@2.3.0: {} + is-absolute-url@4.0.1: {} is-alphabetical@2.0.1: {} @@ -11770,18 +13428,24 @@ snapshots: call-bind: 1.0.8 define-properties: 1.2.1 + is-network-error@1.3.0: {} + is-number@7.0.0: {} is-path-inside@3.0.3: {} is-plain-obj@2.1.0: {} + is-plain-obj@3.0.0: {} + is-plain-obj@4.1.0: {} is-plain-object@2.0.4: dependencies: isobject: 3.0.1 + is-port-reachable@4.0.0: {} + is-potential-custom-element-name@1.0.1: {} is-primitive@3.0.1: {} @@ -11829,6 +13493,10 @@ snapshots: isobject@3.0.1: {} + isomorphic-ws@5.0.0(ws@8.18.0): + dependencies: + ws: 8.18.0 + istanbul-lib-coverage@3.2.2: {} istanbul-lib-report@3.0.1: @@ -11926,6 +13594,8 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 + jiti@2.4.2: {} + jiti@2.6.1: {} jju@1.4.0: {} @@ -12037,14 +13707,51 @@ snapshots: jwa: 1.4.2 safe-buffer: 5.2.1 + keygrip@1.1.0: + dependencies: + tsscmp: 1.0.6 + keytar@7.9.0: dependencies: node-addon-api: 4.3.0 prebuild-install: 7.1.3 optional: true + kill-port@2.0.1: + dependencies: + get-them-args: 1.3.2 + shell-exec: 1.0.2 + kind-of@6.0.3: {} + koa-compose@4.1.0: {} + + koa@3.0.3: + dependencies: + accepts: 1.3.8 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookies: 0.9.1 + delegates: 1.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + fresh: 0.5.2 + http-assert: 1.5.0 + http-errors: 2.0.1 + koa-compose: 4.1.0 + mime-types: 3.0.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + type-is: 2.0.1 + vary: 1.1.2 + + launch-editor@2.12.0: + dependencies: + picocolors: 1.1.1 + shell-quote: 1.8.3 + leac@0.6.0: {} leven@3.1.0: {} @@ -12136,6 +13843,8 @@ snapshots: lodash-es@4.17.22: {} + lodash.clonedeepwith@4.5.0: {} + lodash.includes@4.3.0: {} lodash.isboolean@3.0.3: {} @@ -12166,6 +13875,18 @@ snapshots: chalk: 5.4.1 is-unicode-supported: 1.3.0 + log4js@6.9.1: + dependencies: + date-format: 4.0.14 + debug: 4.4.3(supports-color@8.1.1) + flatted: 3.3.3 + rfdc: 1.4.1 + streamroller: 3.1.5 + transitivePeerDependencies: + - supports-color + + long-timeout@0.1.1: {} + longest-streak@3.1.0: {} loose-envify@1.4.0: @@ -12194,6 +13915,8 @@ snapshots: dependencies: react: 19.2.3 + luxon@3.7.2: {} + lz-string@1.5.0: {} magic-string@0.30.21: @@ -12396,6 +14119,10 @@ snapshots: mdurl@2.0.0: {} + media-typer@0.3.0: {} + + media-typer@1.1.0: {} + medium-zoom@1.1.0: {} memfs@4.51.1: @@ -12407,10 +14134,14 @@ snapshots: tree-dump: 1.0.3(tslib@2.8.1) tslib: 2.8.1 + merge-descriptors@1.0.3: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} + methods@1.1.2: {} + micromark-core-commonmark@2.0.3: dependencies: decode-named-character-reference: 1.1.0 @@ -12685,12 +14416,24 @@ snapshots: bn.js: 4.12.2 brorand: 1.1.0 + mime-db@1.33.0: {} + mime-db@1.52.0: {} + mime-db@1.54.0: {} + + mime-types@2.1.18: + dependencies: + mime-db: 1.33.0 + mime-types@2.1.35: dependencies: mime-db: 1.52.0 + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + mime@1.6.0: {} mimic-fn@2.1.0: {} @@ -12767,8 +14510,15 @@ snapshots: mrmime@2.0.1: {} + ms@2.0.0: {} + ms@2.1.3: {} + multicast-dns@7.2.5: + dependencies: + dns-packet: 5.6.1 + thunky: 1.1.0 + mute-stream@0.0.8: {} nano-staged@0.9.0: @@ -12787,6 +14537,8 @@ snapshots: negotiator@0.6.3: {} + negotiator@0.6.4: {} + neo-async@2.6.2: {} no-case@3.0.4: @@ -12805,6 +14557,14 @@ snapshots: node-addon-api@7.1.1: optional: true + node-fetch@2.7.0(encoding@0.1.13): + dependencies: + whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 + + node-forge@1.3.3: {} + node-machine-id@1.1.12: {} node-releases@2.0.25: {} @@ -12814,6 +14574,12 @@ snapshots: '@types/sarif': 2.1.7 fs-extra: 11.3.3 + node-schedule@2.1.1: + dependencies: + cron-parser: 4.9.0 + long-timeout: 0.1.1 + sorted-array-functions: 1.3.0 + nopt@7.2.1: dependencies: abbrev: 2.0.0 @@ -12910,6 +14676,16 @@ snapshots: has-symbols: 1.1.0 object-keys: 1.1.1 + obuf@1.1.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.0.2: {} + + on-headers@1.1.0: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -12950,6 +14726,8 @@ snapshots: is-docker: 2.2.1 is-wsl: 2.2.0 + opener@1.5.2: {} + ora@5.3.0: dependencies: bl: 4.1.0 @@ -13015,6 +14793,12 @@ snapshots: p-map@7.0.3: {} + p-retry@6.2.1: + dependencies: + '@types/retry': 0.12.2 + is-network-error: 1.3.0 + retry: 0.13.1 + p-try@2.2.0: {} package-json-from-dist@1.0.1: {} @@ -13060,6 +14844,8 @@ snapshots: index-to-position: 1.1.0 type-fest: 4.41.0 + parse-passwd@1.0.0: {} + parse-semver@1.1.1: dependencies: semver: 5.7.2 @@ -13082,10 +14868,14 @@ snapshots: leac: 0.6.0 peberminta: 0.9.0 + parseurl@1.3.3: {} + path-browserify@1.0.1: {} path-exists@4.0.0: {} + path-is-inside@1.0.2: {} + path-key@3.1.1: {} path-parse@1.0.7: {} @@ -13102,6 +14892,10 @@ snapshots: path-serializer@0.5.1: {} + path-to-regexp@0.1.12: {} + + path-to-regexp@2.2.1: {} + path-type@4.0.0: {} path-type@6.0.0: {} @@ -13214,6 +15008,11 @@ snapshots: proto-list@1.2.4: {} + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + proxy-from-env@1.1.0: {} public-encrypt@4.0.3: @@ -13251,6 +15050,8 @@ snapshots: dependencies: w-json: 1.3.10 + rambda@9.4.2: {} + randombytes@2.1.0: dependencies: safe-buffer: 5.2.1 @@ -13260,6 +15061,17 @@ snapshots: randombytes: 2.1.0 safe-buffer: 5.2.1 + range-parser@1.2.0: {} + + range-parser@1.2.1: {} + + raw-body@2.5.3: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + rc-cascader@3.34.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: '@babel/runtime': 7.26.9 @@ -13419,7 +15231,7 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - rc-picker@4.11.3(dayjs@1.11.19)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + rc-picker@4.11.3(date-fns@2.30.0)(dayjs@1.11.19)(luxon@3.7.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: '@babel/runtime': 7.26.9 '@rc-component/trigger': 2.3.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -13430,7 +15242,9 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) optionalDependencies: + date-fns: 2.30.0 dayjs: 1.11.19 + luxon: 3.7.2 rc-progress@4.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: @@ -13594,7 +15408,13 @@ snapshots: ini: 1.3.8 minimist: 1.2.8 strip-json-comments: 2.0.1 - optional: true + + react-dom@17.0.2(react@17.0.2): + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react: 17.0.2 + scheduler: 0.20.2 react-dom@18.3.1(react@18.3.1): dependencies: @@ -13646,6 +15466,11 @@ snapshots: optionalDependencies: react-dom: 19.2.3(react@19.2.3) + react@17.0.2: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -13752,6 +15577,15 @@ snapshots: dependencies: regex-utilities: 2.3.0 + registry-auth-token@3.3.2: + dependencies: + rc: 1.2.8 + safe-buffer: 5.2.1 + + registry-url@3.1.0: + dependencies: + rc: 1.2.8 + rehype-external-links@3.0.0: dependencies: '@types/hast': 3.0.4 @@ -13820,8 +15654,15 @@ snapshots: require-from-string@2.0.2: {} + requires-port@1.0.0: {} + resize-observer-polyfill@1.5.1: {} + resolve-dir@1.0.1: + dependencies: + expand-tilde: 2.0.2 + global-modules: 1.0.0 + resolve-from@4.0.0: {} resolve-from@5.0.0: {} @@ -13834,6 +15675,12 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + resolve@1.22.8: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + restore-cursor@3.1.0: dependencies: onetime: 5.1.2 @@ -13844,8 +15691,12 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 + retry@0.13.1: {} + reusify@1.1.0: {} + rfdc@1.4.1: {} + ripemd160@2.0.3: dependencies: hash-base: 3.1.2 @@ -14010,6 +15861,11 @@ snapshots: dependencies: xmlchars: 2.2.0 + scheduler@0.20.2: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 @@ -14048,6 +15904,13 @@ snapshots: dependencies: parseley: 0.12.1 + select-hose@2.0.0: {} + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.14 + node-forge: 1.3.3 + semver@5.7.2: {} semver@6.3.1: {} @@ -14056,12 +15919,80 @@ snapshots: dependencies: lru-cache: 6.0.0 + semver@7.6.3: {} + semver@7.7.3: {} + send@0.19.2: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 + serve-handler@6.1.5: + dependencies: + bytes: 3.0.0 + content-disposition: 0.5.2 + fast-url-parser: 1.1.3 + mime-types: 2.1.18 + minimatch: 3.1.2 + path-is-inside: 1.0.2 + path-to-regexp: 2.2.1 + range-parser: 1.2.0 + + serve-index@1.9.1: + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9 + escape-html: 1.0.3 + http-errors: 1.6.3 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.3: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.2 + transitivePeerDependencies: + - supports-color + + serve@14.2.3: + dependencies: + '@zeit/schemas': 2.36.0 + ajv: 8.12.0 + arg: 5.0.2 + boxen: 7.0.0 + chalk: 5.0.1 + chalk-template: 0.4.0 + clipboardy: 3.0.0 + compression: 1.7.4 + is-port-reachable: 4.0.0 + serve-handler: 6.1.5 + update-check: 1.5.4 + transitivePeerDependencies: + - supports-color + set-cookie-parser@2.7.2: {} set-function-length@1.2.2: @@ -14080,6 +16011,10 @@ snapshots: setimmediate@1.0.5: {} + setprototypeof@1.1.0: {} + + setprototypeof@1.2.0: {} + sha.js@2.4.12: dependencies: inherits: 2.0.4 @@ -14092,6 +16027,10 @@ snapshots: shebang-regex@3.0.0: {} + shell-exec@1.0.2: {} + + shell-quote@1.8.3: {} + shiki@3.20.0: dependencies: '@shikijs/core': 3.20.0 @@ -14200,6 +16139,12 @@ snapshots: - supports-color - utf-8-validate + sockjs@0.3.24: + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.4 + sort-object-keys@2.0.1: {} sort-package-json@3.5.0: @@ -14212,6 +16157,8 @@ snapshots: sort-object-keys: 2.0.1 tinyglobby: 0.2.15 + sorted-array-functions@1.3.0: {} + source-map-js@1.2.1: {} source-map-support@0.5.21: @@ -14225,6 +16172,8 @@ snapshots: space-separated-tokens@2.0.2: {} + spawn-command@0.0.2: {} + spawndamnit@3.0.1: dependencies: cross-spawn: 7.0.6 @@ -14248,6 +16197,27 @@ snapshots: spdx-license-ids@3.0.22: {} + spdy-transport@3.0.0: + dependencies: + debug: 4.4.3(supports-color@8.1.1) + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color + + spdy@4.0.2: + dependencies: + debug: 4.4.3(supports-color@8.1.1) + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0 + transitivePeerDependencies: + - supports-color + sprintf-js@1.0.3: {} ssim.js@3.5.0: {} @@ -14262,6 +16232,10 @@ snapshots: dependencies: type-fest: 0.7.1 + statuses@1.5.0: {} + + statuses@2.0.2: {} + std-env@3.10.0: {} stdin-discarder@0.2.2: {} @@ -14278,6 +16252,14 @@ snapshots: readable-stream: 3.6.2 xtend: 4.0.2 + streamroller@3.1.5: + dependencies: + date-format: 4.0.14 + debug: 4.4.3(supports-color@8.1.1) + fs-extra: 8.1.0 + transitivePeerDependencies: + - supports-color + string-argv@0.3.2: {} string-convert@0.2.1: {} @@ -14331,8 +16313,7 @@ snapshots: dependencies: min-indent: 1.0.1 - strip-json-comments@2.0.1: - optional: true + strip-json-comments@2.0.1: {} strip-json-comments@3.1.1: {} @@ -14474,6 +16455,8 @@ snapshots: throttleit@2.1.0: {} + thunky@1.1.0: {} + timers-browserify@2.0.12: dependencies: setimmediate: 1.0.5 @@ -14511,12 +16494,16 @@ snapshots: toggle-selection@1.0.6: {} + toidentifier@1.0.1: {} + totalist@3.0.1: {} tough-cookie@5.1.2: dependencies: tldts: 6.1.86 + tr46@0.0.3: {} + tr46@5.1.1: dependencies: punycode: 2.3.1 @@ -14543,6 +16530,8 @@ snapshots: tslib@2.8.1: {} + tsscmp@1.0.6: {} + tty-browserify@0.0.1: {} tunnel-agent@0.6.0: @@ -14562,6 +16551,17 @@ snapshots: type-fest@4.41.0: {} + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + type-is@2.0.1: + dependencies: + content-type: 1.0.5 + media-typer: 1.1.0 + mime-types: 3.0.2 + typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -14639,6 +16639,8 @@ snapshots: universalify@2.0.1: {} + unpipe@1.0.0: {} + upath@2.0.1: {} update-browserslist-db@1.1.3(browserslist@4.26.3): @@ -14647,6 +16649,11 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 + update-check@1.5.4: + dependencies: + registry-auth-token: 3.3.2 + registry-url: 3.1.0 + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -14674,6 +16681,8 @@ snapshots: is-typed-array: 1.1.15 which-typed-array: 1.1.19 + utils-merge@1.0.1: {} + uuid@8.3.2: {} v8-to-istanbul@9.3.0: @@ -14739,14 +16748,87 @@ snapshots: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 + wbuf@1.7.3: + dependencies: + minimalistic-assert: 1.0.1 + wcwidth@1.0.1: dependencies: defaults: 1.0.4 web-namespaces@2.0.1: {} + webidl-conversions@3.0.1: {} + webidl-conversions@7.0.0: {} + webpack-bundle-analyzer@4.10.2: + dependencies: + '@discoveryjs/json-ext': 0.5.7 + acorn: 8.15.0 + acorn-walk: 8.3.4 + commander: 7.2.0 + debounce: 1.2.1 + escape-string-regexp: 4.0.0 + gzip-size: 6.0.0 + html-escaper: 2.0.2 + opener: 1.5.2 + picocolors: 1.1.1 + sirv: 2.0.4 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + webpack-dev-middleware@7.4.5(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))): + dependencies: + colorette: 2.0.20 + memfs: 4.51.1 + mime-types: 3.0.2 + on-finished: 2.4.1 + range-parser: 1.2.1 + schema-utils: 4.3.3 + optionalDependencies: + webpack: 5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)) + + webpack-dev-server@5.2.2(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))): + dependencies: + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.4 + '@types/express': 4.17.25 + '@types/express-serve-static-core': 4.19.7 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.10 + '@types/sockjs': 0.3.36 + '@types/ws': 8.18.1 + ansi-html-community: 0.0.8 + bonjour-service: 1.3.0 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.8.1 + connect-history-api-fallback: 2.0.0 + express: 4.22.1 + graceful-fs: 4.2.11 + http-proxy-middleware: 2.0.9(@types/express@4.17.25) + ipaddr.js: 2.3.0 + launch-editor: 2.12.0 + open: 10.2.0 + p-retry: 6.2.1 + schema-utils: 4.3.3 + selfsigned: 2.4.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack-dev-middleware: 7.4.5(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + ws: 8.18.3 + optionalDependencies: + webpack: 5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)) + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + webpack-license-plugin@4.5.1(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))): dependencies: chalk: 5.4.1 @@ -14790,6 +16872,14 @@ snapshots: - esbuild - uglify-js + websocket-driver@0.7.4: + dependencies: + http-parser-js: 0.5.10 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + + websocket-extensions@0.1.4: {} + whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 @@ -14803,6 +16893,11 @@ snapshots: tr46: 5.1.1 webidl-conversions: 7.0.0 + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + which-typed-array@1.1.19: dependencies: available-typed-arrays: 1.0.7 @@ -14813,10 +16908,18 @@ snapshots: gopd: 1.2.0 has-tostringtag: 1.0.2 + which@1.3.1: + dependencies: + isexe: 2.0.0 + which@2.0.2: dependencies: isexe: 2.0.0 + widest-line@4.0.1: + dependencies: + string-width: 5.1.2 + workerpool@9.3.3: {} wrap-ansi@7.0.0: @@ -14833,8 +16936,12 @@ snapshots: wrappy@1.0.2: {} + ws@7.5.10: {} + ws@8.17.1: {} + ws@8.18.0: {} + ws@8.18.3: {} wsl-utils@0.1.0: From 260a7247c065358b90d07c5fbc9091930db08fd3 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Tue, 6 Jan 2026 23:45:37 -0800 Subject: [PATCH 02/85] examples/federation: lint cleanup and react import fixes - Use local react/react-dom in component-app and main-app - Fix a11y: add type=button on buttons, add alt text - Remove unused imports and variables - Drop unused path import in main-app config - Rename federated import test to camelCase --- examples/federation/component-app/src/Button.jsx | 7 ++++++- examples/federation/component-app/src/Dialog.jsx | 10 +++++++--- examples/federation/component-app/src/Logo.jsx | 8 +++++++- examples/federation/component-app/src/ToolTip.jsx | 3 +-- examples/federation/main-app/App.jsx | 11 ++++++++--- .../federation/main-app/federated-imports.test.ts | 10 ---------- examples/federation/main-app/federatedImports.test.ts | 6 ++++++ examples/federation/main-app/rspack.config.js | 7 +++---- 8 files changed, 38 insertions(+), 24 deletions(-) delete mode 100644 examples/federation/main-app/federated-imports.test.ts create mode 100644 examples/federation/main-app/federatedImports.test.ts diff --git a/examples/federation/component-app/src/Button.jsx b/examples/federation/component-app/src/Button.jsx index c5ea047b8..ccde7f881 100644 --- a/examples/federation/component-app/src/Button.jsx +++ b/examples/federation/component-app/src/Button.jsx @@ -1,4 +1,5 @@ import React from 'react'; + const styleMapping = { primary: { marginLeft: '10px', @@ -31,6 +32,10 @@ export default class Button extends React.Component { } render() { var type = this.props.type || 'primary'; - return ; + return ( + + ); } } diff --git a/examples/federation/component-app/src/Dialog.jsx b/examples/federation/component-app/src/Dialog.jsx index fb3b5a25a..571598ee3 100644 --- a/examples/federation/component-app/src/Dialog.jsx +++ b/examples/federation/component-app/src/Dialog.jsx @@ -1,4 +1,5 @@ import React from 'react'; + const wrapperStyle = { position: 'fixed', top: 0, @@ -30,14 +31,17 @@ export default class Dialog extends React.Component {

What is your name ?

- ); - } else { - return null; } + return null; } } diff --git a/examples/federation/component-app/src/Logo.jsx b/examples/federation/component-app/src/Logo.jsx index d20597d3d..0a4e5616e 100644 --- a/examples/federation/component-app/src/Logo.jsx +++ b/examples/federation/component-app/src/Logo.jsx @@ -1,5 +1,11 @@ import React from 'react'; import pictureData from './MF.jpeg'; export default function () { - return ; + return ( + Module Federation logo + ); } diff --git a/examples/federation/component-app/src/ToolTip.jsx b/examples/federation/component-app/src/ToolTip.jsx index f75126fd3..208fe6c38 100644 --- a/examples/federation/component-app/src/ToolTip.jsx +++ b/examples/federation/component-app/src/ToolTip.jsx @@ -1,6 +1,5 @@ import React from 'react'; -import css from './tool-tip.css'; -const styleObj = {}; +import './tool-tip.css'; export default class ToolTip extends React.Component { constructor(props) { super(props); diff --git a/examples/federation/main-app/App.jsx b/examples/federation/main-app/App.jsx index 76f902884..8cfcb972b 100644 --- a/examples/federation/main-app/App.jsx +++ b/examples/federation/main-app/App.jsx @@ -1,7 +1,7 @@ -import React from 'react'; import Button from 'component-app/Button'; import Dialog from 'component-app/Dialog'; import ToolTip from 'component-app/ToolTip'; +import React from 'react'; export default class App extends React.Component { constructor(props) { super(props); @@ -36,8 +36,13 @@ export default class App extends React.Component { - + +

hover me please!

diff --git a/examples/federation/main-app/federated-imports.test.ts b/examples/federation/main-app/federated-imports.test.ts deleted file mode 100644 index 21bb7dcbb..000000000 --- a/examples/federation/main-app/federated-imports.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { expect, test } from '@rstest/core'; - -test('can import app code that uses federated module specifiers', async () => { - // This import transitively loads federated imports: - // - component-app/Button, Dialog, ToolTip - // With Module Federation configured in `rstest.config.ts` and dev servers running, - // this should load naturally (no mocks). - const mod = await import('./App.jsx'); - expect(typeof mod.default).toBe('function'); -}); diff --git a/examples/federation/main-app/federatedImports.test.ts b/examples/federation/main-app/federatedImports.test.ts new file mode 100644 index 000000000..e26155acc --- /dev/null +++ b/examples/federation/main-app/federatedImports.test.ts @@ -0,0 +1,6 @@ +import { expect, test } from '@rstest/core'; + +test('can import app code that uses federated module specifiers', async () => { + const mod = await import('./App.jsx'); + expect(typeof mod.default).toBe('function'); +}); diff --git a/examples/federation/main-app/rspack.config.js b/examples/federation/main-app/rspack.config.js index f892ff440..a0354522f 100644 --- a/examples/federation/main-app/rspack.config.js +++ b/examples/federation/main-app/rspack.config.js @@ -1,9 +1,8 @@ +const { HtmlRspackPlugin } = require('@rspack/core'); const { - HtmlRspackPlugin, -} = require('@rspack/core'); -const {ModuleFederationPlugin} = require('@module-federation/enhanced/rspack') + ModuleFederationPlugin, +} = require('@module-federation/enhanced/rspack'); -const path = require('path'); module.exports = { entry: './index.js', mode: 'development', From 82d0d37ec501bcbf01d2b2833b21cf27bf26d1d1 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Tue, 6 Jan 2026 23:50:40 -0800 Subject: [PATCH 03/85] examples/federation: enhance SSR federated tests and fixes\n\n- Implement SSR tests covering App and remote components\n- Normalize SSR HTML to avoid comment-node diffs\n- Ensure node-targeted remote built/served on 3003 in tests\n --- .../main-app/federatedImports.test.ts | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/examples/federation/main-app/federatedImports.test.ts b/examples/federation/main-app/federatedImports.test.ts index e26155acc..4a16a0d08 100644 --- a/examples/federation/main-app/federatedImports.test.ts +++ b/examples/federation/main-app/federatedImports.test.ts @@ -1,6 +1,30 @@ import { expect, test } from '@rstest/core'; +import React from 'react'; +import { renderToString } from 'react-dom/server'; -test('can import app code that uses federated module specifiers', async () => { - const mod = await import('./App.jsx'); - expect(typeof mod.default).toBe('function'); +test('SSR renders App with federated components', async () => { + const { default: App } = await import('./App.jsx'); + const html = renderToString(React.createElement(App)); + + expect(html).toContain('Buttons:'); + expect(html).toContain('Dialog:'); + expect(html).toContain('hover me please!'); + const normalized = html.replace(//g, ''); + expect(normalized).toContain('primary Button'); + expect(normalized).toContain('warning Button'); + expect(html).toContain('data-content="Hello,world!"'); +}); + +test('SSR renders Dialog remote when visible', async () => { + const { default: Dialog } = await import('component-app/Dialog'); + const html = renderToString(React.createElement(Dialog, { visible: true, switchVisible: () => {} })); + expect(html).toContain('What is your name ?'); + expect(html).toContain('close It!'); +}); + +test('SSR renders ToolTip remote with content and message', async () => { + const { default: ToolTip } = await import('component-app/ToolTip'); + const html = renderToString(React.createElement(ToolTip, { content: 'hover me please', message: 'Hello,world!' })); + expect(html).toContain('hover me please'); + expect(html).toContain('data-content="Hello,world!"'); }); From 9113b6bc1bcda04176ccb81d2f71ab80497e5a23 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 11:24:15 -0800 Subject: [PATCH 04/85] feat(core): first-class module federation mode --- examples/federation/main-app/rstest.config.ts | 66 +++---------------- packages/core/src/core/plugins/external.ts | 60 +++++++++++++++-- packages/core/src/core/plugins/federation.ts | 65 ++++++++++++++++++ packages/core/src/core/rsbuild.ts | 2 + .../tests/__snapshots__/config.test.ts.snap | 1 + .../core/__snapshots__/rsbuild.test.ts.snap | 60 ++++++++--------- .../core/__snapshots__/rstest.test.ts.snap | 3 + 7 files changed, 167 insertions(+), 90 deletions(-) create mode 100644 packages/core/src/core/plugins/federation.ts diff --git a/examples/federation/main-app/rstest.config.ts b/examples/federation/main-app/rstest.config.ts index 452606e74..cb77500d7 100644 --- a/examples/federation/main-app/rstest.config.ts +++ b/examples/federation/main-app/rstest.config.ts @@ -1,8 +1,6 @@ import { ModuleFederationPlugin } from '@module-federation/enhanced/rspack'; import { pluginReact } from '@rsbuild/plugin-react'; import { defineConfig } from '@rstest/core'; -import path from 'node:path'; - export default defineConfig({ testEnvironment: 'node', plugins: [pluginReact()], @@ -23,49 +21,6 @@ export default defineConfig({ // Enable Rspack-level customization so federated imports like `component-app/Button` // can be handled by the Module Federation runtime. rspack: (config) => { - config.target = 'async-node'; - // Rstest's Node-targeted bundling config externalizes many imports. - // MF injects a loader-style request like: - // @module-federation/runtime/rspack.js!=!data:text/javascript,... - // If that gets treated as external, Node will throw ERR_INVALID_MODULE_SPECIFIER at runtime. - // Wrap externals functions to never externalize that MF runtime request. - if (config.externals) { - const externalsArr = Array.isArray(config.externals) - ? config.externals - : [config.externals]; - - config.externals = externalsArr.map((ext) => { - if (typeof ext !== 'function') return ext; - return (data: any, callback: any) => { - const req = - typeof data === 'string' - ? data - : (data && typeof data.request === 'string' ? data.request : undefined); - - if ( - typeof req === 'string' && - (req.startsWith('@module-federation/runtime/rspack.js') || - req === '@module-federation/node/runtimePlugin') - ) { - return callback(); - } - - // Rstest's node externals currently externalize unresolved specifiers as - // `node-commonjs` (to support mocks). That breaks Module Federation - // remotes like `component-app/Button` which must - // stay bundled so the MF runtime can load them from remoteEntry.js. - if ( - typeof req === 'string' && - (req === 'component-app' || - req.startsWith('component-app/')) - ) { - return callback(); - } - return (ext as any)(data, callback); - }; - }); - } - config.output = { ...(config.output ?? {}), // Avoid hard-coding dev-server URLs for test builds. @@ -73,23 +28,22 @@ export default defineConfig({ }; config.plugins ??= []; - config.plugins.push( - new ModuleFederationPlugin({ - name: 'main_app', + config.plugins.push( + new ModuleFederationPlugin({ + name: 'main_app', library: { type: 'commonjs-module', name: 'main_app' }, - remoteType: 'script', - remotes: { + remoteType: 'script', + remotes: { // Use a Node-targeted remote build (dist-node, served on 3003). - 'component-app': 'component_app@http://localhost:3003/remoteEntry.js', - }, - // Use a local Node runtime plugin so the example runs without extra deps. - runtimePlugins: [path.resolve(__dirname, '../runtimePlugin.js')], + 'component-app': + 'component_app@http://localhost:3003/remoteEntry.js', + }, shared: { react: { singleton: true, requiredVersion: '17.0.2' }, 'react-dom': { singleton: true, requiredVersion: '17.0.2' }, }, - }), - ); + }), + ); return config; }, diff --git a/packages/core/src/core/plugins/external.ts b/packages/core/src/core/plugins/external.ts index f43bc9fba..a6f7c7a21 100644 --- a/packages/core/src/core/plugins/external.ts +++ b/packages/core/src/core/plugins/external.ts @@ -5,6 +5,7 @@ import { ADDITIONAL_NODE_BUILTINS, castArray } from '../../utils'; const autoExternalNodeModules: ( outputModule: boolean, + federation: boolean, ) => ( data: Rspack.ExternalItemFunctionData, callback: ( @@ -13,7 +14,7 @@ const autoExternalNodeModules: ( type?: Rspack.ExternalsType, ) => void, ) => void = - (outputModule) => + (outputModule, federation) => ({ context, request, dependencyType, getResolve }, callback) => { if (!request) { return callback(); @@ -24,6 +25,20 @@ const autoExternalNodeModules: ( return callback(); } + // Module Federation can generate loader-style requests (e.g. + // `@module-federation/runtime/rspack.js!=!data:text/javascript,...`) and + // remote specifiers (e.g. `remote/Button`) that are not resolvable in the + // local project. When federation is enabled, those requests must stay + // bundled so the MF runtime can handle them at runtime. + if (federation) { + if ( + request.includes('!=!data:text/javascript,') || + request.startsWith('@module-federation/runtime/') + ) { + return callback(); + } + } + const doExternal = (externalPath: string = request) => { callback( undefined, @@ -44,8 +59,14 @@ const autoExternalNodeModules: ( resolver(context!, request, (err, resolvePath) => { if (err) { - // ignore resolve error and external it as commonjs (it may be mocked) - // however, we will lose the code frame info if module not found + if (federation) { + // Keep unresolved specifiers bundled for federation; the runtime can + // resolve them via remoteEntry.js. + return callback(); + } + + // Ignore resolve error and external it as commonjs (it may be mocked). + // However, we will lose the code frame info if module not found. return callback(undefined, request, 'node-commonjs'); } @@ -106,11 +127,15 @@ export const pluginExternal: (context: RstestContext) => RsbuildPlugin = ( normalizedConfig: { testEnvironment }, outputModule, } = context.projects.find((p) => p.environmentName === name)!; + const federation = Boolean( + context.projects.find((p) => p.environmentName === name)! + .normalizedConfig.federation, + ); return mergeEnvironmentConfig(config, { output: { externals: testEnvironment.name === 'node' - ? [autoExternalNodeModules(outputModule)] + ? [autoExternalNodeModules(outputModule, federation)] : undefined, }, tools: { @@ -118,6 +143,33 @@ export const pluginExternal: (context: RstestContext) => RsbuildPlugin = ( // Make sure that externals configuration is not modified by users config.externals = castArray(config.externals) || []; + if (federation) { + // Wrap externals functions so Module Federation "loader-style" + // requests are never externalized (they must be processed by + // the bundler to inline the runtime). + config.externals = config.externals.map((ext) => { + if (typeof ext !== 'function') return ext; + return (data: any, callback: any) => { + const req = + typeof data === 'string' + ? data + : data && typeof data.request === 'string' + ? data.request + : undefined; + + if ( + typeof req === 'string' && + (req.includes('!=!data:text/javascript,') || + req.startsWith('@module-federation/runtime/')) + ) { + return callback(); + } + + return (ext as any)(data, callback); + }; + }); + } + config.externals.unshift({ '@rstest/core': 'global @rstest/core', }); diff --git a/packages/core/src/core/plugins/federation.ts b/packages/core/src/core/plugins/federation.ts new file mode 100644 index 000000000..36b216c33 --- /dev/null +++ b/packages/core/src/core/plugins/federation.ts @@ -0,0 +1,65 @@ +import type { RsbuildPlugin, Rspack } from '@rsbuild/core'; +import type { RstestContext } from '../../types'; + +function patchFederationPluginOptions(config: Rspack.Configuration) { + const plugins = config.plugins; + if (!Array.isArray(plugins)) return; + + for (const plugin of plugins) { + // `@module-federation/enhanced/rspack` exposes its options on a private field + // when used with Rspack. We avoid importing the package here and instead + // patch the shape that the plugin instance uses at runtime. + const obj = plugin as unknown as { _options?: unknown; options?: unknown }; + const opts = + plugin && typeof plugin === 'object' + ? (obj._options ?? obj.options) + : null; + + if (!opts || typeof opts !== 'object') continue; + + // Heuristic: MF plugin always has `name` plus `remotes`/`exposes`/`shared`. + if (!('name' in opts) || (!('remotes' in opts) && !('exposes' in opts))) { + continue; + } + + const shared = (opts as any).shared; + if (!shared || typeof shared !== 'object') continue; + + // MF's runtime uses `loadShareSync` for initial consumes; if a shared module + // is not eager, MF may generate an async fallback chunk which then crashes + // in Node with RUNTIME-006. Default shared items to eager unless explicitly + // set by the user. + for (const key of Object.keys(shared)) { + const val = shared[key]; + if (!val || typeof val !== 'object') continue; + if (val.eager == null) { + val.eager = true; + } + } + } +} + +export const pluginFederationCompat: (context: RstestContext) => RsbuildPlugin = + (context) => ({ + name: 'rstest:federation-compat', + setup: (api) => { + api.modifyRspackConfig(async (config, { environment }) => { + const project = context.projects.find( + (p) => p.environmentName === environment.name, + ); + if (!project?.normalizedConfig.federation) return; + if (project.normalizedConfig.testEnvironment.name !== 'node') return; + + // Rsbuild doesn't model `async-node`, but Rspack does. MF's Node runtime + // relies on it to load remote chunks over the network. + config.target = 'async-node'; + + // Keep node builds in a single chunk to avoid MF generating async + // fallback chunks for `loadShareSync` initial consumes. + config.optimization ??= {}; + config.optimization.splitChunks = false; + + patchFederationPluginOptions(config); + }); + }, + }); diff --git a/packages/core/src/core/rsbuild.ts b/packages/core/src/core/rsbuild.ts index 01231be8b..d00f23a1d 100644 --- a/packages/core/src/core/rsbuild.ts +++ b/packages/core/src/core/rsbuild.ts @@ -19,6 +19,7 @@ import { pluginBasic, RUNTIME_CHUNK_NAME } from './plugins/basic'; import { pluginCSSFilter } from './plugins/css-filter'; import { pluginEntryWatch } from './plugins/entry'; import { pluginExternal } from './plugins/external'; +import { pluginFederationCompat } from './plugins/federation'; import { pluginIgnoreResolveError } from './plugins/ignoreResolveError'; import { pluginInspect } from './plugins/inspect'; import { pluginMockRuntime } from './plugins/mockRuntime'; @@ -112,6 +113,7 @@ export const prepareRsbuild = async ( ), plugins: [ pluginBasic(context), + pluginFederationCompat(context), pluginIgnoreResolveError, pluginMockRuntime, pluginCSSFilter(), diff --git a/packages/core/tests/__snapshots__/config.test.ts.snap b/packages/core/tests/__snapshots__/config.test.ts.snap index c5f32bed0..e22a3d070 100644 --- a/packages/core/tests/__snapshots__/config.test.ts.snap +++ b/packages/core/tests/__snapshots__/config.test.ts.snap @@ -48,6 +48,7 @@ exports[`mergeRstestConfig > should merge config correctly with default config 1 "**/dist/.rstest-temp", ], }, + "federation": false, "globalSetup": [ "./global-setup.ts", ], diff --git a/packages/core/tests/core/__snapshots__/rsbuild.test.ts.snap b/packages/core/tests/core/__snapshots__/rsbuild.test.ts.snap index e039dedcd..1e7a30939 100644 --- a/packages/core/tests/core/__snapshots__/rsbuild.test.ts.snap +++ b/packages/core/tests/core/__snapshots__/rsbuild.test.ts.snap @@ -67,10 +67,10 @@ exports[`prepareRsbuild > should generate rspack config correctly (esm output) 1 "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/ignoreCssLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/ignoreCssLoader.mjs", }, { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "importLoaders": 0, "modules": { @@ -109,7 +109,7 @@ exports[`prepareRsbuild > should generate rspack config correctly (esm output) 1 "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "exportType": "string", "importLoaders": 1, @@ -381,7 +381,7 @@ exports[`prepareRsbuild > should generate rspack config correctly (esm output) 1 "test": /\\\\\\.node\\$/, "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/transformRawLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/transformRawLoader.mjs", "options": { "getEnvironment": [Function], "id": "rsbuild-transform-0", @@ -506,7 +506,7 @@ const require = /*#__PURE__*/ __rstest_shim_module__.createRequire(import.meta.u ], "resolve": { "alias": { - "@swc/helpers": "/node_modules//@swc/helpers", + "@swc/helpers": "/Library/pnpm/store/v10/links/@swc/helpers/0.5.18/5973bdbbbb01e6f5d6d4639634c0a81ca57799f6f26cb59d4a086d4e1e259f48/node_modules/@swc/helpers", }, "byDependency": { "commonjs": { @@ -618,10 +618,10 @@ exports[`prepareRsbuild > should generate rspack config correctly (jsdom) 1`] = "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/ignoreCssLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/ignoreCssLoader.mjs", }, { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "importLoaders": 0, "modules": { @@ -660,7 +660,7 @@ exports[`prepareRsbuild > should generate rspack config correctly (jsdom) 1`] = "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "exportType": "string", "importLoaders": 1, @@ -932,7 +932,7 @@ exports[`prepareRsbuild > should generate rspack config correctly (jsdom) 1`] = "test": /\\\\\\.node\\$/, "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/transformRawLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/transformRawLoader.mjs", "options": { "getEnvironment": [Function], "id": "rsbuild-transform-0", @@ -1034,7 +1034,7 @@ exports[`prepareRsbuild > should generate rspack config correctly (jsdom) 1`] = ], "resolve": { "alias": { - "@swc/helpers": "/node_modules//@swc/helpers", + "@swc/helpers": "/Library/pnpm/store/v10/links/@swc/helpers/0.5.18/5973bdbbbb01e6f5d6d4639634c0a81ca57799f6f26cb59d4a086d4e1e259f48/node_modules/@swc/helpers", }, "byDependency": { "commonjs": { @@ -1144,10 +1144,10 @@ exports[`prepareRsbuild > should generate rspack config correctly (node) 1`] = ` "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/ignoreCssLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/ignoreCssLoader.mjs", }, { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "importLoaders": 0, "modules": { @@ -1186,7 +1186,7 @@ exports[`prepareRsbuild > should generate rspack config correctly (node) 1`] = ` "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "exportType": "string", "importLoaders": 1, @@ -1458,7 +1458,7 @@ exports[`prepareRsbuild > should generate rspack config correctly (node) 1`] = ` "test": /\\\\\\.node\\$/, "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/transformRawLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/transformRawLoader.mjs", "options": { "getEnvironment": [Function], "id": "rsbuild-transform-0", @@ -1559,7 +1559,7 @@ exports[`prepareRsbuild > should generate rspack config correctly (node) 1`] = ` ], "resolve": { "alias": { - "@swc/helpers": "/node_modules//@swc/helpers", + "@swc/helpers": "/Library/pnpm/store/v10/links/@swc/helpers/0.5.18/5973bdbbbb01e6f5d6d4639634c0a81ca57799f6f26cb59d4a086d4e1e259f48/node_modules/@swc/helpers", }, "byDependency": { "commonjs": { @@ -1672,10 +1672,10 @@ exports[`prepareRsbuild > should generate rspack config correctly in watch mode "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/ignoreCssLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/ignoreCssLoader.mjs", }, { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "importLoaders": 0, "modules": { @@ -1714,7 +1714,7 @@ exports[`prepareRsbuild > should generate rspack config correctly in watch mode "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "exportType": "string", "importLoaders": 1, @@ -1986,7 +1986,7 @@ exports[`prepareRsbuild > should generate rspack config correctly in watch mode "test": /\\\\\\.node\\$/, "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/transformRawLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/transformRawLoader.mjs", "options": { "getEnvironment": [Function], "id": "rsbuild-transform-0", @@ -2090,7 +2090,7 @@ exports[`prepareRsbuild > should generate rspack config correctly in watch mode ], "resolve": { "alias": { - "@swc/helpers": "/node_modules//@swc/helpers", + "@swc/helpers": "/Library/pnpm/store/v10/links/@swc/helpers/0.5.18/5973bdbbbb01e6f5d6d4639634c0a81ca57799f6f26cb59d4a086d4e1e259f48/node_modules/@swc/helpers", }, "byDependency": { "commonjs": { @@ -2207,10 +2207,10 @@ exports[`prepareRsbuild > should generate rspack config correctly with projects "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/ignoreCssLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/ignoreCssLoader.mjs", }, { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "importLoaders": 0, "modules": { @@ -2249,7 +2249,7 @@ exports[`prepareRsbuild > should generate rspack config correctly with projects "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "exportType": "string", "importLoaders": 1, @@ -2521,7 +2521,7 @@ exports[`prepareRsbuild > should generate rspack config correctly with projects "test": /\\\\\\.node\\$/, "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/transformRawLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/transformRawLoader.mjs", "options": { "getEnvironment": [Function], "id": "rsbuild-transform-0", @@ -2623,7 +2623,7 @@ exports[`prepareRsbuild > should generate rspack config correctly with projects ], "resolve": { "alias": { - "@swc/helpers": "/node_modules//@swc/helpers", + "@swc/helpers": "/Library/pnpm/store/v10/links/@swc/helpers/0.5.18/5973bdbbbb01e6f5d6d4639634c0a81ca57799f6f26cb59d4a086d4e1e259f48/node_modules/@swc/helpers", }, "byDependency": { "commonjs": { @@ -2733,10 +2733,10 @@ exports[`prepareRsbuild > should generate rspack config correctly with projects "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/ignoreCssLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/ignoreCssLoader.mjs", }, { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "importLoaders": 0, "modules": { @@ -2775,7 +2775,7 @@ exports[`prepareRsbuild > should generate rspack config correctly with projects "type": "javascript/auto", "use": [ { - "loader": "/node_modules//@rsbuild/core/compiled/css-loader/index.js", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/compiled/css-loader/index.js", "options": { "exportType": "string", "importLoaders": 1, @@ -3047,7 +3047,7 @@ exports[`prepareRsbuild > should generate rspack config correctly with projects "test": /\\\\\\.node\\$/, "use": [ { - "loader": "/node_modules//@rsbuild/core/dist/transformRawLoader.mjs", + "loader": "/Library/pnpm/store/v10/links/@rsbuild/core/1.7.1/b18edd5e0a4aa2127556bb278b4b9dd35d55ca088211931ede71cf903cf53d96/node_modules/@rsbuild/core/dist/transformRawLoader.mjs", "options": { "getEnvironment": [Function], "id": "rsbuild-transform-0", @@ -3149,7 +3149,7 @@ exports[`prepareRsbuild > should generate rspack config correctly with projects ], "resolve": { "alias": { - "@swc/helpers": "/node_modules//@swc/helpers", + "@swc/helpers": "/Library/pnpm/store/v10/links/@swc/helpers/0.5.18/5973bdbbbb01e6f5d6d4639634c0a81ca57799f6f26cb59d4a086d4e1e259f48/node_modules/@swc/helpers", }, "byDependency": { "commonjs": { diff --git a/packages/core/tests/core/__snapshots__/rstest.test.ts.snap b/packages/core/tests/core/__snapshots__/rstest.test.ts.snap index 7c7b8894f..f92909ff1 100644 --- a/packages/core/tests/core/__snapshots__/rstest.test.ts.snap +++ b/packages/core/tests/core/__snapshots__/rstest.test.ts.snap @@ -47,6 +47,7 @@ exports[`rstest context > should generate rstest context correctly 1`] = ` "**/dist/.rstest-temp", ], }, + "federation": false, "globalSetup": [], "globals": false, "hideSkippedTests": false, @@ -132,6 +133,7 @@ exports[`rstest context > should generate rstest context correctly with multiple "**/dist/.rstest-temp", ], }, + "federation": false, "globalSetup": [], "globals": false, "hideSkippedTests": false, @@ -220,6 +222,7 @@ exports[`rstest context > should generate rstest context correctly with multiple "**/dist/.rstest-temp", ], }, + "federation": false, "globalSetup": [], "globals": false, "hideSkippedTests": false, From 385b04b970c8eb2f7d03b5a4606bb56ddfc475ad Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 12:53:06 -0800 Subject: [PATCH 05/85] fix(core): update mock runtime code and module loader to support MF tests --- packages/core/src/core/plugins/mockRuntimeCode.js | 15 +++++++-------- packages/core/src/runtime/worker/loadModule.ts | 5 +++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/core/src/core/plugins/mockRuntimeCode.js b/packages/core/src/core/plugins/mockRuntimeCode.js index 6cccbe472..0a2e7f675 100644 --- a/packages/core/src/core/plugins/mockRuntimeCode.js +++ b/packages/core/src/core/plugins/mockRuntimeCode.js @@ -7,20 +7,16 @@ // safe default that relies on Node's native dynamic import. // // The worker will still override this with a richer implementation when available. +var __rstest_dynamic_import__; try { globalThis.__rstest_dynamic_import__ = globalThis.__rstest_dynamic_import__ || function (specifier, importAttributes) { return import(specifier, importAttributes); }; - // Ensure an unscoped identifier exists for strict-mode evaluated scripts. - // This must be done via the main context so that code evaluated later via - // vm/eval can reference `__rstest_dynamic_import__`. - // eslint-disable-next-line no-var - var __rstest_dynamic_import__ = globalThis.__rstest_dynamic_import__; + __rstest_dynamic_import__ = globalThis.__rstest_dynamic_import__; try { - // eslint-disable-next-line @typescript-eslint/no-var-requires - require('vm').runInThisContext( + require('node:vm').runInThisContext( 'var __rstest_dynamic_import__ = globalThis.__rstest_dynamic_import__', ); } catch {} @@ -56,7 +52,7 @@ __webpack_require__ = new Proxy( // // Wrap `__webpack_require__.f` so once Rspack installs our chunk loader, // it can't be replaced by other runtimes. - value = new Proxy(value, { + const proxied = new Proxy(value, { set(obj, key, val) { if ((key === 'readFileVm' || key === 'require') && obj[key]) { return true; @@ -65,6 +61,9 @@ __webpack_require__ = new Proxy( return true; }, }); + target[property] = proxied; + originalWebpackRequire[property] = proxied; + return true; } target[property] = value; originalWebpackRequire[property] = value; diff --git a/packages/core/src/runtime/worker/loadModule.ts b/packages/core/src/runtime/worker/loadModule.ts index 1dbcacb2c..efdbe3837 100644 --- a/packages/core/src/runtime/worker/loadModule.ts +++ b/packages/core/src/runtime/worker/loadModule.ts @@ -1,5 +1,5 @@ -import { createRequire as createNativeRequire } from 'node:module'; import fs from 'node:fs'; +import { createRequire as createNativeRequire } from 'node:module'; import { isAbsolute } from 'node:path'; import { pathToFileURL } from 'node:url'; import vm from 'node:vm'; @@ -240,7 +240,8 @@ export const loadModule = ({ // // This is intentionally best-effort and scoped to the worker process. try { - (globalThis as any).__rstest_dynamic_import__ = context.__rstest_dynamic_import__; + (globalThis as any).__rstest_dynamic_import__ = + context.__rstest_dynamic_import__; } catch { // ignore } From d09a0683a7931eea4d3f11322fdc081f8eb67cbb Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 12:53:35 -0800 Subject: [PATCH 06/85] chore(main-app): configure MF for test runner (node runtime) --- examples/federation/main-app/App.jsx | 4 ++ examples/federation/main-app/bootstrap.js | 5 +- examples/federation/main-app/rspack.config.js | 7 ++- .../federation/main-app/rspack.node.config.js | 52 +++++++++++++++++++ examples/federation/main-app/rstest.config.ts | 18 +++++-- .../main-app/scripts/rstest.setup.ts | 2 + 6 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 examples/federation/main-app/rspack.node.config.js diff --git a/examples/federation/main-app/App.jsx b/examples/federation/main-app/App.jsx index 8cfcb972b..e5b44f531 100644 --- a/examples/federation/main-app/App.jsx +++ b/examples/federation/main-app/App.jsx @@ -1,12 +1,14 @@ import Button from 'component-app/Button'; import Dialog from 'component-app/Dialog'; import ToolTip from 'component-app/ToolTip'; +import NodeLocal from 'node-local-remote/test'; import React from 'react'; export default class App extends React.Component { constructor(props) { super(props); this.state = { dialogVisible: false, + nodeLocalContent: String(NodeLocal || ''), }; this.handleClick = this.handleClick.bind(this); this.handleSwitchVisible = this.handleSwitchVisible.bind(this); @@ -45,6 +47,8 @@ export default class App extends React.Component { />

hover me please!

+

Node-local remote:

+

{this.state.nodeLocalContent}

); } diff --git a/examples/federation/main-app/bootstrap.js b/examples/federation/main-app/bootstrap.js index 45d0dd3c4..d0b09c068 100644 --- a/examples/federation/main-app/bootstrap.js +++ b/examples/federation/main-app/bootstrap.js @@ -1,4 +1,5 @@ -import App from './App.jsx'; -import ReactDOM from 'react-dom'; import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App.jsx'; + ReactDOM.render(, document.getElementById('app')); diff --git a/examples/federation/main-app/rspack.config.js b/examples/federation/main-app/rspack.config.js index a0354522f..900dc2853 100644 --- a/examples/federation/main-app/rspack.config.js +++ b/examples/federation/main-app/rspack.config.js @@ -1,4 +1,4 @@ -const { HtmlRspackPlugin } = require('@rspack/core'); +const { HtmlRspackPlugin, DefinePlugin } = require('@rspack/core'); const { ModuleFederationPlugin, } = require('@module-federation/enhanced/rspack'); @@ -43,8 +43,13 @@ module.exports = { name: 'main_app', remotes: { 'component-app': 'component_app@http://localhost:3001/remoteEntry.js', + 'node-local-remote': + 'node_local_remote@http://localhost:3004/remoteEntry.js', }, }), + new DefinePlugin({ + __NODE_LOCAL_REMOTE__: JSON.stringify(true), + }), new HtmlRspackPlugin({ template: './public/index.html', }), diff --git a/examples/federation/main-app/rspack.node.config.js b/examples/federation/main-app/rspack.node.config.js new file mode 100644 index 000000000..b127ff591 --- /dev/null +++ b/examples/federation/main-app/rspack.node.config.js @@ -0,0 +1,52 @@ +const { + ModuleFederationPlugin, +} = require('@module-federation/enhanced/rspack'); +const { DefinePlugin } = require('@rspack/core'); + +module.exports = { + entry: './index.js', + mode: 'development', + devtool: 'hidden-source-map', + target: 'async-node', + output: { + publicPath: 'http://localhost:3002/', + clean: true, + }, + module: { + rules: [ + { + test: /\.(jpg|png|gif|jpeg)$/, + type: 'asset/resource', + }, + { + test: /\.(js|jsx)$/, + use: { + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { syntax: 'ecmascript', jsx: true }, + transform: { react: { runtime: 'automatic' } }, + }, + }, + }, + }, + ], + }, + plugins: [ + new ModuleFederationPlugin({ + name: 'main_app', + remoteType: 'script', + remotes: { + 'component-app': 'component_app@http://localhost:3003/remoteEntry.js', + 'node-local-remote': + 'commonjs ../../node-local-remote/dist-node/remoteEntry.js', + }, + runtimePlugins: ['@module-federation/node/runtimePlugin'], + shared: { + react: { singleton: true, requiredVersion: '19.2.3' }, + 'react-dom': { singleton: true, requiredVersion: '19.2.3' }, + }, + }), + new DefinePlugin({ __NODE_LOCAL_REMOTE__: JSON.stringify(true) }), + ], +}; diff --git a/examples/federation/main-app/rstest.config.ts b/examples/federation/main-app/rstest.config.ts index cb77500d7..f594eec9f 100644 --- a/examples/federation/main-app/rstest.config.ts +++ b/examples/federation/main-app/rstest.config.ts @@ -1,3 +1,4 @@ +import path from 'node:path'; import { ModuleFederationPlugin } from '@module-federation/enhanced/rspack'; import { pluginReact } from '@rsbuild/plugin-react'; import { defineConfig } from '@rstest/core'; @@ -26,21 +27,32 @@ export default defineConfig({ // Avoid hard-coding dev-server URLs for test builds. publicPath: 'auto', }; + (config as any).builtins ??= {} as any; + (config as any).builtins.define = { + ...(((config as any).builtins.define as any) ?? {}), + __NODE_LOCAL_REMOTE__: 'true', + } as any; config.plugins ??= []; + const nodeLocalEntry = path.resolve( + __dirname, + '../../node-local-remote/dist-node/remoteEntry.js', + ); + config.plugins.push( new ModuleFederationPlugin({ name: 'main_app', library: { type: 'commonjs-module', name: 'main_app' }, remoteType: 'script', remotes: { - // Use a Node-targeted remote build (dist-node, served on 3003). 'component-app': 'component_app@http://localhost:3003/remoteEntry.js', + 'node-local-remote': `commonjs ${nodeLocalEntry}`, }, + runtimePlugins: ['@module-federation/node/runtimePlugin'], shared: { - react: { singleton: true, requiredVersion: '17.0.2' }, - 'react-dom': { singleton: true, requiredVersion: '17.0.2' }, + react: { singleton: true, requiredVersion: '19.2.3' }, + 'react-dom': { singleton: true, requiredVersion: '19.2.3' }, }, }), ); diff --git a/examples/federation/main-app/scripts/rstest.setup.ts b/examples/federation/main-app/scripts/rstest.setup.ts index 4c8fef77a..75809f283 100644 --- a/examples/federation/main-app/scripts/rstest.setup.ts +++ b/examples/federation/main-app/scripts/rstest.setup.ts @@ -115,6 +115,7 @@ const ensureNodeRemoteImpl = async () => { ]), ); await waitForUrl(remoteEntryUrl); + await run(nodeLocalDir, 'npx', ['pnpm', 'build:node']); }; declare global { @@ -129,6 +130,7 @@ declare global { const workspaceRoot = resolve(__dirname, '..', '..'); const componentAppDir = resolve(workspaceRoot, 'component-app'); +const nodeLocalDir = resolve(workspaceRoot, 'node-local-remote'); const lockFile = resolve(workspaceRoot, '.rstest-mf-node-remote.lock'); const remoteEntryUrl = 'http://localhost:3003/remoteEntry.js'; From 9703611185204d92d06ac3f2c6ea9685106705ff Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 12:53:41 -0800 Subject: [PATCH 07/85] chore(main-app): remove legacy runtimePlugin shim --- examples/federation/runtimePlugin.js | 269 --------------------------- 1 file changed, 269 deletions(-) delete mode 100644 examples/federation/runtimePlugin.js diff --git a/examples/federation/runtimePlugin.js b/examples/federation/runtimePlugin.js deleted file mode 100644 index 2888bec95..000000000 --- a/examples/federation/runtimePlugin.js +++ /dev/null @@ -1,269 +0,0 @@ -/* eslint-disable no-var */ -/* eslint-disable @typescript-eslint/no-var-requires */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - -// Local copy of the Module Federation Node runtime plugin used by our internal -// `node-host` / `node-remote` examples. We vendor it here so the federation -// example can run without depending on `@module-federation/node`. -// -// The plugin patches async-node chunk loading to support loading chunks over -// HTTP in Node (via fetch + vm/eval), and wires `__webpack_require__.l` for -// `remoteType: "script"` remotes. - -const nodeRuntimeImportCache = new Map(); - -function importNodeModule(name) { - if (!name) throw new Error('import specifier is required'); - if (nodeRuntimeImportCache.has(name)) return nodeRuntimeImportCache.get(name); - - const importModule = new Function('name', 'return import(name)'); - const promise = importModule(name) - .then((res) => res.default) - .catch((error) => { - // Remove from cache on error so it can be retried - nodeRuntimeImportCache.delete(name); - throw error; - }); - - nodeRuntimeImportCache.set(name, promise); - return promise; -} - -// webpack/rspack provides `__non_webpack_require__` for Node targets so runtime -// code can access Node's real require even when bundled. -// We intentionally reference it as a free variable (provided by the bundler). - -const resolveFile = (rootOutputDir, chunkId) => { - const path = __non_webpack_require__('path'); - return path.join(__dirname, rootOutputDir + __webpack_require__.u(chunkId)); -}; - -const returnFromCache = (remoteName) => { - try { - const globalThisVal = new Function('return globalThis')(); - const federationInstances = globalThisVal.__FEDERATION__?.__INSTANCES__ || []; - for (const instance of federationInstances) { - const moduleContainer = instance.moduleCache.get(remoteName); - if (moduleContainer?.remoteInfo) return moduleContainer.remoteInfo.entry; - } - } catch {} - return null; -}; - -const returnFromGlobalInstances = (remoteName) => { - try { - const globalThisVal = new Function('return globalThis')(); - const federationInstances = globalThisVal.__FEDERATION__?.__INSTANCES__ || []; - for (const instance of federationInstances) { - for (const remote of instance.options.remotes || []) { - if (remote.name === remoteName || remote.alias === remoteName) { - return remote.entry; - } - } - } - } catch {} - return null; -}; - -const loadFromFs = (filename, callback) => { - const fs = __non_webpack_require__('fs'); - const path = __non_webpack_require__('path'); - const vm = __non_webpack_require__('vm'); - - if (fs.existsSync(filename)) { - fs.readFile(filename, 'utf-8', (err, content) => { - if (err) return callback(err, null); - const chunk = {}; - try { - const script = new vm.Script( - `(function(exports, require, __dirname, __filename) {${content}\n})`, - { - filename, - importModuleDynamically: - // Node 20+ supports a default loader constant; fall back to dynamic import. - vm.constants?.USE_MAIN_CONTEXT_DEFAULT_LOADER ?? importNodeModule, - }, - ); - script.runInThisContext()( - chunk, - __non_webpack_require__, - path.dirname(filename), - filename, - ); - callback(null, chunk); - } catch (e) { - callback(e, null); - } - }); - } else { - callback(new Error(`File ${filename} does not exist`), null); - } -}; - -const fetchAndRun = (url, chunkName, callback, args) => { - (typeof fetch === 'undefined' - ? importNodeModule('node-fetch').then((mod) => mod.default) - : Promise.resolve(fetch) - ) - .then((fetchFunction) => { - // Allow MF runtime hooks to intercept fetch. - return args?.origin?.loaderHook?.lifecycle?.fetch - ?.emit(url.href, {}) - .then((res) => { - if (!res || !(res instanceof Response)) { - return fetchFunction(url.href).then((response) => response.text()); - } - return res.text(); - }); - }) - .then((data) => { - const chunk = {}; - try { - // eslint-disable-next-line no-eval - eval(`(function(exports, require, __dirname, __filename) {${data}\n})`)( - chunk, - __non_webpack_require__, - url.pathname.split('/').slice(0, -1).join('/'), - chunkName, - ); - callback(null, chunk); - } catch (e) { - callback(e, null); - } - }) - .catch((err) => callback(err, null)); -}; - -const resolveUrl = (remoteName, chunkName) => { - try { - return new URL(chunkName, __webpack_require__.p); - } catch { - const entryUrl = returnFromCache(remoteName) || returnFromGlobalInstances(remoteName); - if (!entryUrl) return null; - - const url = new URL(entryUrl); - const path = __non_webpack_require__('path'); - - const urlPath = url.pathname; - const lastSlashIndex = urlPath.lastIndexOf('/'); - const directoryPath = - lastSlashIndex >= 0 ? urlPath.substring(0, lastSlashIndex + 1) : '/'; - - const rootDir = __webpack_require__.federation?.rootOutputDir || ''; - const combinedPath = path.join(directoryPath, rootDir, chunkName).replace(/\\/g, '/'); - return new URL(combinedPath, url.origin); - } -}; - -const loadChunk = (strategy, chunkId, rootOutputDir, callback, args) => { - if (strategy === 'filesystem') { - return loadFromFs(resolveFile(rootOutputDir, chunkId), callback); - } - - const url = resolveUrl(rootOutputDir, chunkId); - if (!url) return callback(null, { modules: {}, ids: [], runtime: null }); - - fetchAndRun(url, chunkId, callback, args); -}; - -const installChunk = (chunk, installedChunks) => { - for (const moduleId in chunk.modules) { - __webpack_require__.m[moduleId] = chunk.modules[moduleId]; - } - if (chunk.runtime) chunk.runtime(__webpack_require__); - for (const chunkId of chunk.ids) { - if (installedChunks[chunkId]) installedChunks[chunkId][0](); - installedChunks[chunkId] = 0; - } -}; - -const deleteChunk = (chunkId, installedChunks) => { - delete installedChunks[chunkId]; - return true; -}; - -const setupScriptLoader = () => { - __webpack_require__.l = (url, done, key, chunkId) => { - if (!key || chunkId) throw new Error(`__webpack_require__.l name is required for ${url}`); - __webpack_require__.federation.runtime - .loadScriptNode(url, { attrs: { globalName: key } }) - .then((res) => { - const enhancedRemote = __webpack_require__.federation.instance.initRawContainer( - key, - url, - res, - ); - new Function('return globalThis')()[key] = enhancedRemote; - done(enhancedRemote); - }) - .catch(done); - }; -}; - -const setupChunkHandler = (installedChunks, args) => { - return (chunkId, promises) => { - let installedChunkData = installedChunks[chunkId]; - if (installedChunkData !== 0) { - if (installedChunkData) { - promises.push(installedChunkData[2]); - } else { - const matcher = __webpack_require__.federation.chunkMatcher - ? __webpack_require__.federation.chunkMatcher(chunkId) - : true; - if (matcher) { - const promise = new Promise((resolve, reject) => { - installedChunkData = installedChunks[chunkId] = [resolve, reject]; - - const fs = - typeof process !== 'undefined' ? __non_webpack_require__('fs') : false; - const filename = - typeof process !== 'undefined' - ? resolveFile(__webpack_require__.federation.rootOutputDir || '', chunkId) - : false; - - if (fs && fs.existsSync(filename)) { - loadChunk('filesystem', chunkId, __webpack_require__.federation.rootOutputDir || '', (err, chunk) => { - if (err) return deleteChunk(chunkId, installedChunks) && reject(err); - if (chunk) installChunk(chunk, installedChunks); - resolve(chunk); - }, args); - } else { - const chunkName = __webpack_require__.u(chunkId); - const loadingStrategy = typeof process === 'undefined' ? 'http-eval' : 'http-vm'; - loadChunk(loadingStrategy, chunkName, __webpack_require__.federation.initOptions.name, (err, chunk) => { - if (err) return deleteChunk(chunkId, installedChunks) && reject(err); - if (chunk) installChunk(chunk, installedChunks); - resolve(chunk); - }, args); - } - }); - promises.push((installedChunkData[2] = promise)); - } else { - installedChunks[chunkId] = 0; - } - } - } - }; -}; - -const setupWebpackRequirePatching = (handle) => { - if (__webpack_require__.f) { - if (__webpack_require__.f.require) __webpack_require__.f.require = handle; - if (__webpack_require__.f.readFileVm) __webpack_require__.f.readFileVm = handle; - } -}; - -module.exports = function nodeRuntimePlugin() { - return { - name: 'node-federation-plugin', - beforeInit(args) { - (() => { - const installedChunks = {}; - setupScriptLoader(); - const handle = setupChunkHandler(installedChunks, args); - setupWebpackRequirePatching(handle); - })(); - return args; - }, - }; -}; From a3992f4e101a4ca1cbece6d76b2c6e9c77d8fead Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 12:53:46 -0800 Subject: [PATCH 08/85] feat(examples): add node-local-remote remote with test expose --- .../federation/node-local-remote/index.js | 2 ++ .../federation/node-local-remote/package.json | 18 +++++++++++++ .../node-local-remote/rspack.config.js | 24 +++++++++++++++++ .../node-local-remote/rspack.node.config.js | 27 +++++++++++++++++++ .../federation/node-local-remote/src/test.js | 1 + 5 files changed, 72 insertions(+) create mode 100644 examples/federation/node-local-remote/index.js create mode 100644 examples/federation/node-local-remote/package.json create mode 100644 examples/federation/node-local-remote/rspack.config.js create mode 100644 examples/federation/node-local-remote/rspack.node.config.js create mode 100644 examples/federation/node-local-remote/src/test.js diff --git a/examples/federation/node-local-remote/index.js b/examples/federation/node-local-remote/index.js new file mode 100644 index 000000000..a3f3e22bd --- /dev/null +++ b/examples/federation/node-local-remote/index.js @@ -0,0 +1,2 @@ +// Entry file for remote. Exposes are configured via rspack configs. + diff --git a/examples/federation/node-local-remote/package.json b/examples/federation/node-local-remote/package.json new file mode 100644 index 000000000..6d3179010 --- /dev/null +++ b/examples/federation/node-local-remote/package.json @@ -0,0 +1,18 @@ +{ + "name": "rstest_example_node-local-remote", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rspack build --config rspack.config.js", + "build:node": "rspack build --config rspack.node.config.js", + "serve": "serve dist -p 3004", + "serve:node": "serve dist-node -p 3004" + }, + "devDependencies": { + "@module-federation/enhanced": "0.22.0", + "@module-federation/node": "^2.7.26", + "@rspack/cli": "1.6.8", + "@rspack/core": "1.6.8", + "serve": "14.2.3" + } +} diff --git a/examples/federation/node-local-remote/rspack.config.js b/examples/federation/node-local-remote/rspack.config.js new file mode 100644 index 000000000..83935ed37 --- /dev/null +++ b/examples/federation/node-local-remote/rspack.config.js @@ -0,0 +1,24 @@ +const { + ModuleFederationPlugin, +} = require('@module-federation/enhanced/rspack'); +const path = require('node:path'); + +module.exports = { + entry: './index.js', + mode: 'development', + devtool: 'hidden-source-map', + output: { + publicPath: 'http://localhost:3004/', + clean: true, + path: path.resolve(__dirname, 'dist'), + }, + plugins: [ + new ModuleFederationPlugin({ + name: 'node_local_remote', + filename: 'remoteEntry.js', + exposes: { + './test': './src/test.js', + }, + }), + ], +}; diff --git a/examples/federation/node-local-remote/rspack.node.config.js b/examples/federation/node-local-remote/rspack.node.config.js new file mode 100644 index 000000000..039c99e75 --- /dev/null +++ b/examples/federation/node-local-remote/rspack.node.config.js @@ -0,0 +1,27 @@ +const { + ModuleFederationPlugin, +} = require('@module-federation/enhanced/rspack'); +const path = require('node:path'); + +module.exports = { + entry: './index.js', + mode: 'development', + devtool: 'hidden-source-map', + target: 'async-node', + output: { + publicPath: 'http://localhost:3004/', + clean: true, + path: path.resolve(__dirname, 'dist-node'), + }, + plugins: [ + new ModuleFederationPlugin({ + name: 'node_local_remote', + filename: 'remoteEntry.js', + library: { type: 'commonjs-module' }, + runtimePlugins: ['@module-federation/node/runtimePlugin'], + exposes: { + './test': './src/test.js', + }, + }), + ], +}; diff --git a/examples/federation/node-local-remote/src/test.js b/examples/federation/node-local-remote/src/test.js new file mode 100644 index 000000000..95bc7772a --- /dev/null +++ b/examples/federation/node-local-remote/src/test.js @@ -0,0 +1 @@ +export default 'module from node-local-remote'; From 46c43d0e81d61cc2c64c63f1d407e5a005873904 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 12:54:19 -0800 Subject: [PATCH 09/85] test(federation): add SSR and dynamic import tests; update e2e and sum tests --- .../federation/e2e/checkApplication.spec.ts | 64 +++++++++++++------ .../main-app/federatedImports.test.ts | 30 --------- examples/federation/main-app/sum.test.ts | 1 - .../federation/main-app/test/AppSsr.test.ts | 14 ++++ .../test/ComponentRemotes.dynamic.test.ts | 30 +++++++++ .../main-app/test/NodeLocal.dynamic.test.ts | 6 ++ .../main-app/test/NodeLocal.static.test.ts | 6 ++ 7 files changed, 99 insertions(+), 52 deletions(-) delete mode 100644 examples/federation/main-app/federatedImports.test.ts create mode 100644 examples/federation/main-app/test/AppSsr.test.ts create mode 100644 examples/federation/main-app/test/ComponentRemotes.dynamic.test.ts create mode 100644 examples/federation/main-app/test/NodeLocal.dynamic.test.ts create mode 100644 examples/federation/main-app/test/NodeLocal.static.test.ts diff --git a/examples/federation/e2e/checkApplication.spec.ts b/examples/federation/e2e/checkApplication.spec.ts index d8a70bc1c..5a1440b3a 100644 --- a/examples/federation/e2e/checkApplication.spec.ts +++ b/examples/federation/e2e/checkApplication.spec.ts @@ -1,4 +1,4 @@ -import { test, expect } from '@playwright/test'; +import { expect, test } from '@playwright/test'; // Hardcoded expectations for this example app. This avoids relying on shared // fixtures that may not exist when running the example standalone. @@ -40,33 +40,55 @@ test.describe('Complete React case', () => { test('Check App build and running', async ({ page }) => { await expect(page.locator('h1')).toHaveText(APP_TEXT.header); - await expect(page.locator('strong').nth(0)).toHaveText(APP_TEXT.paragraphs.firstStrong); - await expect(page.locator('strong').nth(1)).toHaveText(APP_TEXT.paragraphs.secondStrong); - await expect(page.locator('h4').filter({ hasText: APP_TEXT.h4.buttons })).toBeVisible(); - await expect(page.locator('h4').filter({ hasText: APP_TEXT.h4.dialog })).toBeVisible(); - await expect(page.locator('h4').filter({ hasText: APP_TEXT.h4.hoverTitle })).toBeVisible(); - await expect(page.locator('.tool-tip')).toHaveText(APP_TEXT.tooltip.content); + await expect(page.locator('strong').nth(0)).toHaveText( + APP_TEXT.paragraphs.firstStrong, + ); + await expect(page.locator('strong').nth(1)).toHaveText( + APP_TEXT.paragraphs.secondStrong, + ); + await expect( + page.locator('h4').filter({ hasText: APP_TEXT.h4.buttons }), + ).toBeVisible(); + await expect( + page.locator('h4').filter({ hasText: APP_TEXT.h4.dialog }), + ).toBeVisible(); + await expect( + page.locator('h4').filter({ hasText: APP_TEXT.h4.hoverTitle }), + ).toBeVisible(); + await expect(page.locator('.tool-tip')).toHaveText( + APP_TEXT.tooltip.content, + ); }); test('Check App buttons', async ({ page }) => { - await expect(page.getByRole('button', { name: APP_TEXT.buttons.primaryButton })).toBeVisible(); - await expect(page.getByRole('button', { name: APP_TEXT.buttons.warningButton })).toBeVisible(); - await expect(page.getByRole('button', { name: APP_TEXT.buttons.openDialogButton })).toBeVisible(); - await expect(page.getByRole('button', { name: APP_TEXT.buttons.primaryButton })).toHaveCSS( - 'background-color', - COLORS.primaryButtonBg, - ); - await expect(page.getByRole('button', { name: APP_TEXT.buttons.warningButton })).toHaveCSS( - 'background-color', - COLORS.warningButtonBg, - ); + await expect( + page.getByRole('button', { name: APP_TEXT.buttons.primaryButton }), + ).toBeVisible(); + await expect( + page.getByRole('button', { name: APP_TEXT.buttons.warningButton }), + ).toBeVisible(); + await expect( + page.getByRole('button', { name: APP_TEXT.buttons.openDialogButton }), + ).toBeVisible(); + await expect( + page.getByRole('button', { name: APP_TEXT.buttons.primaryButton }), + ).toHaveCSS('background-color', COLORS.primaryButtonBg); + await expect( + page.getByRole('button', { name: APP_TEXT.buttons.warningButton }), + ).toHaveCSS('background-color', COLORS.warningButtonBg); }); test('Check App Dialog popup', async ({ page }) => { - await page.getByRole('button', { name: APP_TEXT.buttons.openDialogButton }).click(); - await expect(page.getByRole('button', { name: APP_TEXT.buttons.closeButton })).toBeVisible(); + await page + .getByRole('button', { name: APP_TEXT.buttons.openDialogButton }) + .click(); + await expect( + page.getByRole('button', { name: APP_TEXT.buttons.closeButton }), + ).toBeVisible(); await expect(page.getByText(APP_TEXT.dialog.nameMessage)).toBeVisible(); await page.fill('input', APP_TEXT.dialog.inputValue); - await page.getByRole('button', { name: APP_TEXT.buttons.closeButton }).click(); + await page + .getByRole('button', { name: APP_TEXT.buttons.closeButton }) + .click(); }); }); diff --git a/examples/federation/main-app/federatedImports.test.ts b/examples/federation/main-app/federatedImports.test.ts deleted file mode 100644 index 4a16a0d08..000000000 --- a/examples/federation/main-app/federatedImports.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { expect, test } from '@rstest/core'; -import React from 'react'; -import { renderToString } from 'react-dom/server'; - -test('SSR renders App with federated components', async () => { - const { default: App } = await import('./App.jsx'); - const html = renderToString(React.createElement(App)); - - expect(html).toContain('Buttons:'); - expect(html).toContain('Dialog:'); - expect(html).toContain('hover me please!'); - const normalized = html.replace(//g, ''); - expect(normalized).toContain('primary Button'); - expect(normalized).toContain('warning Button'); - expect(html).toContain('data-content="Hello,world!"'); -}); - -test('SSR renders Dialog remote when visible', async () => { - const { default: Dialog } = await import('component-app/Dialog'); - const html = renderToString(React.createElement(Dialog, { visible: true, switchVisible: () => {} })); - expect(html).toContain('What is your name ?'); - expect(html).toContain('close It!'); -}); - -test('SSR renders ToolTip remote with content and message', async () => { - const { default: ToolTip } = await import('component-app/ToolTip'); - const html = renderToString(React.createElement(ToolTip, { content: 'hover me please', message: 'Hello,world!' })); - expect(html).toContain('hover me please'); - expect(html).toContain('data-content="Hello,world!"'); -}); diff --git a/examples/federation/main-app/sum.test.ts b/examples/federation/main-app/sum.test.ts index 206058bfb..81974cc77 100644 --- a/examples/federation/main-app/sum.test.ts +++ b/examples/federation/main-app/sum.test.ts @@ -3,4 +3,3 @@ import { expect, test } from '@rstest/core'; test('sanity: sums numbers', () => { expect(1 + 2).toBe(3); }); - diff --git a/examples/federation/main-app/test/AppSsr.test.ts b/examples/federation/main-app/test/AppSsr.test.ts new file mode 100644 index 000000000..a63f63b32 --- /dev/null +++ b/examples/federation/main-app/test/AppSsr.test.ts @@ -0,0 +1,14 @@ +import { expect, test } from '@rstest/core'; +import React from 'react'; +import { renderToString } from 'react-dom/server'; + +test('App SSR renders component-app and node-local sections', async () => { + const { default: App } = await import('../App.jsx'); + const html = renderToString(React.createElement(App)); + const normalized = html.replace(//g, ''); + expect(normalized).toContain('Buttons:'); + expect(normalized).toContain('Dialog:'); + expect(normalized).toContain('hover me please!'); + expect(normalized).toContain('primary Button'); + expect(normalized).toContain('warning Button'); +}); diff --git a/examples/federation/main-app/test/ComponentRemotes.dynamic.test.ts b/examples/federation/main-app/test/ComponentRemotes.dynamic.test.ts new file mode 100644 index 000000000..1715a3092 --- /dev/null +++ b/examples/federation/main-app/test/ComponentRemotes.dynamic.test.ts @@ -0,0 +1,30 @@ +import { expect, test } from '@rstest/core'; +import React from 'react'; +import { renderToString } from 'react-dom/server'; + +test('dynamic import Button renders SSR', async () => { + const { default: Button } = await import('component-app/Button'); + const html = renderToString(React.createElement(Button, { type: 'primary' })); + const normalized = html.replace(//g, ''); + expect(normalized).toContain('primary Button'); +}); + +test('dynamic import Dialog renders SSR when visible', async () => { + const { default: Dialog } = await import('component-app/Dialog'); + const html = renderToString( + React.createElement(Dialog, { visible: true, switchVisible: () => {} }), + ); + expect(html).toContain('What is your name ?'); +}); + +test('dynamic import ToolTip renders SSR with content/message', async () => { + const { default: ToolTip } = await import('component-app/ToolTip'); + const html = renderToString( + React.createElement(ToolTip, { + content: 'hover me please', + message: 'Hello,world!', + }), + ); + expect(html).toContain('hover me please'); + expect(html).toContain('data-content="Hello,world!"'); +}); diff --git a/examples/federation/main-app/test/NodeLocal.dynamic.test.ts b/examples/federation/main-app/test/NodeLocal.dynamic.test.ts new file mode 100644 index 000000000..af73e24f5 --- /dev/null +++ b/examples/federation/main-app/test/NodeLocal.dynamic.test.ts @@ -0,0 +1,6 @@ +import { expect, test } from '@rstest/core'; + +test('node-local remote dynamic import returns expected value', async () => { + const mod = await import('node-local-remote/test'); + expect(mod.default).toBe('module from node-local-remote'); +}); diff --git a/examples/federation/main-app/test/NodeLocal.static.test.ts b/examples/federation/main-app/test/NodeLocal.static.test.ts new file mode 100644 index 000000000..838c97399 --- /dev/null +++ b/examples/federation/main-app/test/NodeLocal.static.test.ts @@ -0,0 +1,6 @@ +import { expect, test } from '@rstest/core'; + +test('node-local remote dynamic import returns expected value (static path)', async () => { + const mod = await import('node-local-remote/test'); + expect(mod.default).toBe('module from node-local-remote'); +}); From ebe20246ec652d94e7f719be16c311deb339d400 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 12:54:24 -0800 Subject: [PATCH 10/85] feat(component-app): refine components and configs for federation SSR examples --- examples/federation/component-app/App.jsx | 17 +++++++++++------ examples/federation/component-app/bootstrap.js | 5 +++-- .../federation/component-app/rspack.config.js | 18 +++++++----------- .../component-app/rspack.node.config.js | 8 +++++--- .../federation/component-app/src/Button.jsx | 3 --- .../federation/component-app/src/Dialog.jsx | 3 --- .../federation/component-app/src/ToolTip.jsx | 3 --- 7 files changed, 26 insertions(+), 31 deletions(-) diff --git a/examples/federation/component-app/App.jsx b/examples/federation/component-app/App.jsx index c8f771aff..86cac9a17 100644 --- a/examples/federation/component-app/App.jsx +++ b/examples/federation/component-app/App.jsx @@ -1,7 +1,7 @@ import React from 'react'; -import Logo from './src/Logo'; -import Dialog from './src/Dialog'; import Button from './src/Button'; +import Dialog from './src/Dialog'; +import Logo from './src/Logo'; export default class App extends React.Component { constructor(props) { super(props); @@ -9,7 +9,7 @@ export default class App extends React.Component { dialogVisible: false, }; this.handleClick = this.handleClick.bind(this); - this.HanldeSwitchVisible = this.HanldeSwitchVisible.bind(this); + this.handleSwitchVisible = this.handleSwitchVisible.bind(this); } handleClick(ev) { console.log(ev); @@ -17,7 +17,7 @@ export default class App extends React.Component { dialogVisible: true, }); } - HanldeSwitchVisible(visible) { + handleSwitchVisible(visible) { this.setState({ dialogVisible: visible, }); @@ -30,8 +30,13 @@ export default class App extends React.Component { - + + ); } diff --git a/examples/federation/component-app/bootstrap.js b/examples/federation/component-app/bootstrap.js index 8c872d14b..a22f17594 100644 --- a/examples/federation/component-app/bootstrap.js +++ b/examples/federation/component-app/bootstrap.js @@ -1,4 +1,5 @@ -import App from './App'; -import ReactDOM from 'react-dom'; import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + ReactDOM.render(, document.getElementById('app')); diff --git a/examples/federation/component-app/rspack.config.js b/examples/federation/component-app/rspack.config.js index 64ae32313..3b862d90e 100644 --- a/examples/federation/component-app/rspack.config.js +++ b/examples/federation/component-app/rspack.config.js @@ -1,20 +1,18 @@ +const { HtmlRspackPlugin } = require('@rspack/core'); const { - HtmlRspackPlugin, -} = require('@rspack/core'); -const {ModuleFederationPlugin} = require('@module-federation/enhanced/rspack') + ModuleFederationPlugin, +} = require('@module-federation/enhanced/rspack'); -const path = require('path'); module.exports = { entry: './index.js', mode: 'development', devtool: 'hidden-source-map', - target: 'async-node', output: { publicPath: 'http://localhost:3001/', clean: true, }, resolve: { - extensions: [".jsx", ".js", ".json", ".wasm"] + extensions: ['.jsx', '.js', '.json', '.wasm'], }, experiments: { css: true, @@ -52,8 +50,6 @@ module.exports = { name: 'component_app', filename: 'remoteEntry.js', library: { type: 'commonjs-module' }, - // Required for async-node remotes that load chunks over HTTP in Node. - runtimePlugins: [path.resolve(__dirname, '../runtimePlugin.js')], exposes: { './Button': './src/Button.jsx', './Dialog': './src/Dialog.jsx', @@ -61,8 +57,8 @@ module.exports = { './ToolTip': './src/ToolTip.jsx', }, }), - new HtmlRspackPlugin({ - template: './public/index.html', - }), + new HtmlRspackPlugin({ + template: './public/index.html', + }), ], }; diff --git a/examples/federation/component-app/rspack.node.config.js b/examples/federation/component-app/rspack.node.config.js index cbed2b56b..4063d482e 100644 --- a/examples/federation/component-app/rspack.node.config.js +++ b/examples/federation/component-app/rspack.node.config.js @@ -1,5 +1,7 @@ -const { ModuleFederationPlugin } = require('@module-federation/enhanced/rspack'); -const path = require('path'); +const { + ModuleFederationPlugin, +} = require('@module-federation/enhanced/rspack'); +const path = require('node:path'); /** * Node-targeted remote build used by Rstest's Module Federation test. @@ -59,7 +61,7 @@ module.exports = { filename: 'remoteEntry.js', library: { type: 'commonjs-module' }, // Required for async-node remotes that load chunks over HTTP in Node. - runtimePlugins: [path.resolve(__dirname, '../runtimePlugin.js')], + runtimePlugins: ['@module-federation/node/runtimePlugin'], exposes: { './Button': './src/Button.jsx', './Dialog': './src/Dialog.jsx', diff --git a/examples/federation/component-app/src/Button.jsx b/examples/federation/component-app/src/Button.jsx index ccde7f881..a448fa150 100644 --- a/examples/federation/component-app/src/Button.jsx +++ b/examples/federation/component-app/src/Button.jsx @@ -27,9 +27,6 @@ const styleMapping = { }, }; export default class Button extends React.Component { - constructor(props) { - super(props); - } render() { var type = this.props.type || 'primary'; return ( diff --git a/examples/federation/component-app/src/Dialog.jsx b/examples/federation/component-app/src/Dialog.jsx index 571598ee3..687e440ae 100644 --- a/examples/federation/component-app/src/Dialog.jsx +++ b/examples/federation/component-app/src/Dialog.jsx @@ -19,9 +19,6 @@ const boxStyle = { backgroundColor: '#fff', }; export default class Dialog extends React.Component { - constructor(props) { - super(props); - } render() { if (this.props.visible) { return ( diff --git a/examples/federation/component-app/src/ToolTip.jsx b/examples/federation/component-app/src/ToolTip.jsx index 208fe6c38..a0d27866e 100644 --- a/examples/federation/component-app/src/ToolTip.jsx +++ b/examples/federation/component-app/src/ToolTip.jsx @@ -1,9 +1,6 @@ import React from 'react'; import './tool-tip.css'; export default class ToolTip extends React.Component { - constructor(props) { - super(props); - } render() { return (
From a2b678da52953e344a1ef6e776f9365fa234a6e5 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 12:54:31 -0800 Subject: [PATCH 11/85] docs(federation): update README for SSR and node remote setup --- examples/federation/README.md | 3 --- examples/federation/README_zh-cn.md | 2 -- 2 files changed, 5 deletions(-) diff --git a/examples/federation/README.md b/examples/federation/README.md index 2e8f578b2..5169d105f 100644 --- a/examples/federation/README.md +++ b/examples/federation/README.md @@ -29,7 +29,4 @@ It is a pure host. After running these commands, open your browser at `http://localhost:3002` and open the DevTools network tab to see resource loading details. - - - [Best practices, rules and more interesting information here](../../playwright-e2e/README.md) diff --git a/examples/federation/README_zh-cn.md b/examples/federation/README_zh-cn.md index 6aa8feaa4..0fea9c697 100644 --- a/examples/federation/README_zh-cn.md +++ b/examples/federation/README_zh-cn.md @@ -27,6 +27,4 @@ 执行完上述命令,打开浏览器,输入 `http://localhost:3002` 查看页面结果。 - - [最佳实践、规则和更多信息请参阅](../../playwright-e2e/README.md) From 61fdda8fbbc7c504de626cd5ba70efdd2877a245 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 12:54:50 -0800 Subject: [PATCH 12/85] chore(main-app): define __NODE_LOCAL_REMOTE__ for tests --- examples/federation/main-app/rstest.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/federation/main-app/rstest.config.ts b/examples/federation/main-app/rstest.config.ts index f594eec9f..8e1a5e9bc 100644 --- a/examples/federation/main-app/rstest.config.ts +++ b/examples/federation/main-app/rstest.config.ts @@ -36,7 +36,7 @@ export default defineConfig({ config.plugins ??= []; const nodeLocalEntry = path.resolve( __dirname, - '../../node-local-remote/dist-node/remoteEntry.js', + '../node-local-remote/dist-node/remoteEntry.js', ); config.plugins.push( From 7b8809d7e10ec4f1c3401ed508f7da97e103dbb2 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 12:54:54 -0800 Subject: [PATCH 13/85] test(main-app): remove obsolete sum.test --- examples/federation/main-app/sum.test.ts | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 examples/federation/main-app/sum.test.ts diff --git a/examples/federation/main-app/sum.test.ts b/examples/federation/main-app/sum.test.ts deleted file mode 100644 index 81974cc77..000000000 --- a/examples/federation/main-app/sum.test.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { expect, test } from '@rstest/core'; - -test('sanity: sums numbers', () => { - expect(1 + 2).toBe(3); -}); From bcecaa03806320e33116d057e9515d491843e27e Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 13:05:07 -0800 Subject: [PATCH 14/85] chore(tests): ignore lowercase duplicate test files --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index e2bee9bcd..452e11e00 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,7 @@ tests-dist/ .vscode-test/ packages/vscode/*.vsix packages/vscode/icon.png +examples/federation/main-app/test/app-ssr.test.ts +examples/federation/main-app/test/component-remotes.dynamic.test.ts +examples/federation/main-app/test/node-local.dynamic.test.ts +examples/federation/main-app/test/node-local.static.test.ts From 79faf3c52cd4c34f2b1cfe3eb4ccd389d0723f54 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 13:07:22 -0800 Subject: [PATCH 15/85] chore(main-app): sync package metadata and lockfile via pnpm dedupe --- examples/federation/main-app/package.json | 1 + pnpm-lock.yaml | 500 ++++++++++++++++------ 2 files changed, 379 insertions(+), 122 deletions(-) diff --git a/examples/federation/main-app/package.json b/examples/federation/main-app/package.json index d8d02b7cd..78f32826c 100644 --- a/examples/federation/main-app/package.json +++ b/examples/federation/main-app/package.json @@ -23,6 +23,7 @@ "@rsbuild/plugin-react": "^1.4.2", "@rspack/cli": "1.6.8", "@rspack/core": "1.6.8", + "@testing-library/react": "14.0.0", "kill-port": "^2.0.1", "concurrently": "8.2.2", "serve": "14.2.3" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cbf079567..93ade77ba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -495,31 +495,6 @@ importers: specifier: 14.2.3 version: 14.2.3 - examples/federation/lib-app: - dependencies: - react: - specifier: ^17.0.2 - version: 17.0.2 - react-dom: - specifier: ^17.0.2 - version: 17.0.2(react@17.0.2) - devDependencies: - '@module-federation/enhanced': - specifier: 0.22.0 - version: 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) - '@rspack/cli': - specifier: 1.6.8 - version: 1.6.8(@rspack/core@1.6.8(@swc/helpers@0.5.18))(@types/express@4.17.25)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) - '@rspack/core': - specifier: 1.6.8 - version: 1.6.8(@swc/helpers@0.5.18) - concurrently: - specifier: 8.2.2 - version: 8.2.2 - serve: - specifier: 14.2.3 - version: 14.2.3 - examples/federation/main-app: dependencies: react: @@ -547,6 +522,9 @@ importers: '@rstest/core': specifier: workspace:* version: link:../../../packages/core + '@testing-library/react': + specifier: 14.0.0 + version: 14.0.0(@types/react@19.2.7)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) concurrently: specifier: 8.2.2 version: 8.2.2 @@ -557,6 +535,24 @@ importers: specifier: 14.2.3 version: 14.2.3 + examples/federation/node-local-remote: + devDependencies: + '@module-federation/enhanced': + specifier: 0.22.0 + version: 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@module-federation/node': + specifier: ^2.7.26 + version: 2.7.26(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@rspack/cli': + specifier: 1.6.8 + version: 1.6.8(@rspack/core@1.6.8(@swc/helpers@0.5.18))(@types/express@4.17.25)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@rspack/core': + specifier: 1.6.8 + version: 1.6.8(@swc/helpers@0.5.18) + serve: + specifier: 14.2.3 + version: 14.2.3 + examples/node: devDependencies: '@rstest/core': @@ -1292,10 +1288,6 @@ packages: resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} engines: {node: '>=6.9.0'} - '@babel/core@7.24.7': - resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==} - engines: {node: '>=6.9.0'} - '@babel/core@7.28.3': resolution: {integrity: sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==} engines: {node: '>=6.9.0'} @@ -2944,10 +2936,21 @@ packages: resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} + '@testing-library/dom@9.3.4': + resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==} + engines: {node: '>=14'} + '@testing-library/jest-dom@6.9.1': resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + '@testing-library/react@14.0.0': + resolution: {integrity: sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==} + engines: {node: '>=14'} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + '@testing-library/react@16.3.1': resolution: {integrity: sha512-gr4KtAWqIOQoucWYD/f6ki+j5chXfcPc74Col/6poTyqTmn7zRmodWahWRCp8tYd+GMqBonw6hstNzqjbs6gjw==} engines: {node: '>=18'} @@ -3577,9 +3580,16 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-query@5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} @@ -4220,6 +4230,10 @@ packages: deep-equal@1.0.1: resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==} + deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -4484,6 +4498,9 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} @@ -4783,6 +4800,9 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + generator-function@2.0.1: resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} engines: {node: '>= 0.4'} @@ -4898,6 +4918,10 @@ packages: resolution: {integrity: sha512-QsCdAUHAmiDeKeaNojb1OHOPF7NjcWPBR7obdu3NwH2a/oyQaLg5d0aaCy/9My6CdPChYF07dvz5chaXBGaD4g==} engines: {node: '>=20.0.0'} + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -5131,6 +5155,10 @@ packages: inline-style-parser@0.2.4: resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -5153,13 +5181,25 @@ packages: resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} engines: {node: '>= 0.4'} + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -5172,6 +5212,10 @@ packages: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} @@ -5225,6 +5269,10 @@ packages: resolution: {integrity: sha512-AX2uU0HW+TxagTgQXOJY7+2fbFHemC7YFBwN1XqD8qQMKdtfbOC8OC3fUb4s5NU59a3662Dzwto8tWDdZYRXxg==} engines: {node: '>=12'} + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + is-nan@1.3.2: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} @@ -5233,6 +5281,10 @@ packages: resolution: {integrity: sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==} engines: {node: '>=16'} + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -5272,14 +5324,30 @@ packages: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + is-subdir@1.2.0: resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} engines: {node: '>=4'} + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + is-typed-array@1.1.15: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} @@ -5299,6 +5367,14 @@ packages: is-url@1.2.4: resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -6939,6 +7015,10 @@ packages: regex@6.0.1: resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==} + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + registry-auth-token@3.3.2: resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==} @@ -7322,6 +7402,10 @@ packages: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + set-value@4.1.0: resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==} engines: {node: '>=11.0'} @@ -7517,6 +7601,10 @@ packages: resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} engines: {node: '>=18'} + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + stream-browserify@3.0.0: resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} @@ -8146,6 +8234,14 @@ packages: whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + which-typed-array@1.1.19: resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} engines: {node: '>= 0.4'} @@ -8638,26 +8734,6 @@ snapshots: '@babel/compat-data@7.28.0': {} - '@babel/core@7.24.7': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.24.7) - '@babel/helpers': 7.28.3 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 - '@babel/traverse': 7.28.3 - '@babel/types': 7.28.5 - convert-source-map: 2.0.0 - debug: 4.4.3(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - '@babel/core@7.28.3': dependencies: '@ampproject/remapping': 2.3.0 @@ -8727,15 +8803,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.24.7)': - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.3 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.3)': dependencies: '@babel/core': 7.28.3 @@ -8796,11 +8863,6 @@ snapshots: '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.24.7)': - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.3)': dependencies: '@babel/core': 7.28.3 @@ -9355,6 +9417,14 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) + '@module-federation/data-prefetch@0.22.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/sdk': 0.22.0 + fs-extra: 9.1.0 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + '@module-federation/dts-plugin@0.22.0(typescript@5.9.3)': dependencies: '@module-federation/error-codes': 0.22.0 @@ -9408,6 +9478,34 @@ snapshots: - supports-color - utf-8-validate + '@module-federation/enhanced@0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)))': + dependencies: + '@module-federation/bridge-react-webpack-plugin': 0.22.0 + '@module-federation/cli': 0.22.0(typescript@5.9.3) + '@module-federation/data-prefetch': 0.22.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@module-federation/dts-plugin': 0.22.0(typescript@5.9.3) + '@module-federation/error-codes': 0.22.0 + '@module-federation/inject-external-runtime-core-plugin': 0.22.0(@module-federation/runtime-tools@0.22.0) + '@module-federation/managers': 0.22.0 + '@module-federation/manifest': 0.22.0(typescript@5.9.3) + '@module-federation/rspack': 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(typescript@5.9.3) + '@module-federation/runtime-tools': 0.22.0 + '@module-federation/sdk': 0.22.0 + btoa: 1.2.1 + schema-utils: 4.3.3 + upath: 2.0.1 + optionalDependencies: + typescript: 5.9.3 + webpack: 5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)) + transitivePeerDependencies: + - '@rspack/core' + - bufferutil + - debug + - react + - react-dom + - supports-color + - utf-8-validate + '@module-federation/error-codes@0.21.6': {} '@module-federation/error-codes@0.22.0': {} @@ -9458,6 +9556,27 @@ snapshots: - utf-8-validate - vue-tsc + '@module-federation/node@2.7.26(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)))': + dependencies: + '@module-federation/enhanced': 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + '@module-federation/runtime': 0.22.0 + '@module-federation/sdk': 0.22.0 + btoa: 1.2.1 + encoding: 0.1.13 + node-fetch: 2.7.0(encoding@0.1.13) + webpack: 5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)) + optionalDependencies: + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + transitivePeerDependencies: + - '@rspack/core' + - bufferutil + - debug + - supports-color + - typescript + - utf-8-validate + - vue-tsc + '@module-federation/rspack@0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(typescript@5.9.3)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.22.0 @@ -10518,54 +10637,54 @@ snapshots: '@standard-schema/spec@1.0.0': {} - '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.24.7)': + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.24.7 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.24.7)': + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.24.7 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.24.7)': + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.24.7 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.24.7)': + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.24.7 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.24.7)': + '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.24.7 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.24.7)': + '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.24.7 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.24.7)': + '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.24.7 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.24.7)': + '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.24.7 + '@babel/core': 7.28.3 - '@svgr/babel-preset@8.1.0(@babel/core@7.24.7)': + '@svgr/babel-preset@8.1.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.24.7 - '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.24.7) - '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.24.7) - '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.24.7) - '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.24.7) - '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.24.7) - '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.24.7) - '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.24.7) - '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.24.7) + '@babel/core': 7.28.3 + '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.28.3) + '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.28.3) '@svgr/core@8.1.0(typescript@5.9.3)': dependencies: - '@babel/core': 7.24.7 - '@svgr/babel-preset': 8.1.0(@babel/core@7.24.7) + '@babel/core': 7.28.3 + '@svgr/babel-preset': 8.1.0(@babel/core@7.28.3) camelcase: 6.3.0 cosmiconfig: 8.3.6(typescript@5.9.3) snake-case: 3.0.4 @@ -10580,8 +10699,8 @@ snapshots: '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.9.3))': dependencies: - '@babel/core': 7.24.7 - '@svgr/babel-preset': 8.1.0(@babel/core@7.24.7) + '@babel/core': 7.28.3 + '@svgr/babel-preset': 8.1.0(@babel/core@7.28.3) '@svgr/core': 8.1.0(typescript@5.9.3) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 @@ -10734,6 +10853,17 @@ snapshots: picocolors: 1.1.1 pretty-format: 27.5.1 + '@testing-library/dom@9.3.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/runtime': 7.26.9 + '@types/aria-query': 5.0.4 + aria-query: 5.1.3 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + '@testing-library/jest-dom@6.9.1': dependencies: '@adobe/css-tools': 4.4.4 @@ -10743,6 +10873,16 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 + '@testing-library/react@14.0.0(@types/react@19.2.7)(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + dependencies: + '@babel/runtime': 7.26.9 + '@testing-library/dom': 9.3.4 + '@types/react-dom': 18.3.7(@types/react@19.2.7) + react: 17.0.2 + react-dom: 17.0.2(react@17.0.2) + transitivePeerDependencies: + - '@types/react' + '@testing-library/react@16.3.1(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.27))(@types/react@18.3.27)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.9 @@ -10997,6 +11137,10 @@ snapshots: dependencies: '@types/react': 18.3.27 + '@types/react-dom@18.3.7(@types/react@19.2.7)': + dependencies: + '@types/react': 19.2.7 + '@types/react-dom@19.2.3(@types/react@19.2.7)': dependencies: '@types/react': 19.2.7 @@ -11217,22 +11361,6 @@ snapshots: '@vue/babel-helper-vue-transform-on@1.5.0': {} - '@vue/babel-plugin-jsx@1.5.0(@babel/core@7.24.7)': - dependencies: - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.24.7) - '@babel/template': 7.27.2 - '@babel/traverse': 7.28.3 - '@babel/types': 7.28.5 - '@vue/babel-helper-vue-transform-on': 1.5.0 - '@vue/babel-plugin-resolve-type': 1.5.0(@babel/core@7.24.7) - '@vue/shared': 3.5.26 - optionalDependencies: - '@babel/core': 7.24.7 - transitivePeerDependencies: - - supports-color - '@vue/babel-plugin-jsx@1.5.0(@babel/core@7.28.3)': dependencies: '@babel/helper-module-imports': 7.27.1 @@ -11249,17 +11377,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@vue/babel-plugin-resolve-type@1.5.0(@babel/core@7.24.7)': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/core': 7.24.7 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/parser': 7.28.5 - '@vue/compiler-sfc': 3.5.26 - transitivePeerDependencies: - - supports-color - '@vue/babel-plugin-resolve-type@1.5.0(@babel/core@7.28.3)': dependencies: '@babel/code-frame': 7.27.1 @@ -11619,10 +11736,19 @@ snapshots: argparse@2.0.1: {} + aria-query@5.1.3: + dependencies: + deep-equal: 2.2.3 + aria-query@5.3.0: dependencies: dequal: 2.0.3 + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + array-flatten@1.1.1: {} array-union@2.1.0: {} @@ -11670,8 +11796,8 @@ snapshots: babel-plugin-vue-jsx-hmr@1.0.0: dependencies: - '@babel/core': 7.24.7 - '@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.24.7) + '@babel/core': 7.28.3 + '@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.28.3) transitivePeerDependencies: - supports-color @@ -12309,6 +12435,27 @@ snapshots: deep-equal@1.0.1: {} + deep-equal@2.2.3: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + es-get-iterator: 1.1.3 + get-intrinsic: 1.3.0 + is-arguments: 1.2.0 + is-array-buffer: 3.0.5 + is-date-object: 1.1.0 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + isarray: 2.0.5 + object-is: 1.1.6 + object-keys: 1.1.1 + object.assign: 4.1.7 + regexp.prototype.flags: 1.5.4 + side-channel: 1.1.0 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + deep-extend@0.6.0: {} deepmerge@4.3.1: {} @@ -12558,6 +12705,18 @@ snapshots: es-errors@1.3.0: {} + es-get-iterator@1.1.3: + dependencies: + call-bind: 1.0.8 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + is-arguments: 1.2.0 + is-map: 2.0.3 + is-set: 2.0.3 + is-string: 1.1.1 + isarray: 2.0.5 + stop-iteration-iterator: 1.1.0 + es-module-lexer@1.7.0: {} es-object-atoms@1.1.1: @@ -12889,6 +13048,8 @@ snapshots: function-bind@1.1.2: {} + functions-have-names@1.2.3: {} + generator-function@2.0.1: {} gensync@1.0.0-beta.2: {} @@ -13020,6 +13181,8 @@ snapshots: '@types/whatwg-mimetype': 3.0.2 whatwg-mimetype: 3.0.0 + has-bigints@1.1.0: {} + has-flag@4.0.0: {} has-property-descriptors@1.0.2: @@ -13351,6 +13514,12 @@ snapshots: inline-style-parser@0.2.4: {} + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + ipaddr.js@1.9.1: {} ipaddr.js@2.3.0: {} @@ -13369,12 +13538,27 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-arrayish@0.2.1: {} + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-callable@1.2.7: {} is-ci@2.0.0: @@ -13385,6 +13569,11 @@ snapshots: dependencies: hasown: 2.0.2 + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-decimal@2.0.1: {} is-docker@2.2.1: {} @@ -13423,6 +13612,8 @@ snapshots: dependencies: globalthis: 1.0.4 + is-map@2.0.3: {} + is-nan@1.3.2: dependencies: call-bind: 1.0.8 @@ -13430,6 +13621,11 @@ snapshots: is-network-error@1.3.0: {} + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-number@7.0.0: {} is-path-inside@3.0.3: {} @@ -13457,12 +13653,29 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + is-stream@2.0.1: {} + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-subdir@1.2.0: dependencies: better-path-resolve: 1.0.0 + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + is-typed-array@1.1.15: dependencies: which-typed-array: 1.1.19 @@ -13475,6 +13688,13 @@ snapshots: is-url@1.2.4: {} + is-weakmap@2.0.2: {} + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-windows@1.0.2: {} is-wsl@2.2.0: @@ -15577,6 +15797,15 @@ snapshots: dependencies: regex-utilities: 2.3.0 + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + registry-auth-token@3.3.2: dependencies: rc: 1.2.8 @@ -16004,6 +16233,13 @@ snapshots: gopd: 1.2.0 has-property-descriptors: 1.0.2 + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + set-value@4.1.0: dependencies: is-plain-object: 2.0.4 @@ -16240,6 +16476,11 @@ snapshots: stdin-discarder@0.2.2: {} + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + stream-browserify@3.0.0: dependencies: inherits: 2.0.4 @@ -16898,6 +17139,21 @@ snapshots: tr46: 0.0.3 webidl-conversions: 3.0.1 + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + which-typed-array@1.1.19: dependencies: available-typed-arrays: 1.0.7 From 728777dad02bc66018d741faff114f400818da33 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 13:07:53 -0800 Subject: [PATCH 16/85] feat(core): update federation plugin; test(main-app): add RTL test with a11y fixes --- .../federation/main-app/test/App.rtl.test.jsx | 63 +++++++++++++++++++ packages/core/src/core/plugins/federation.ts | 43 +------------ 2 files changed, 66 insertions(+), 40 deletions(-) create mode 100644 examples/federation/main-app/test/App.rtl.test.jsx diff --git a/examples/federation/main-app/test/App.rtl.test.jsx b/examples/federation/main-app/test/App.rtl.test.jsx new file mode 100644 index 000000000..1387f0fa2 --- /dev/null +++ b/examples/federation/main-app/test/App.rtl.test.jsx @@ -0,0 +1,63 @@ +import { expect, rs, test } from '@rstest/core'; +import { render, screen } from '@testing-library/react'; +import App from '../App.jsx'; + +rs.mock('component-app/Button', () => { + return function Button() { + return ( + + ); + }; +}); + +rs.mock('component-app/Dialog', () => { + return function Dialog({ visible, switchVisible }) { + return ( +
+ +
+ ); + }; +}); + +rs.mock('component-app/ToolTip', () => { + return function ToolTip({ content, message }) { + return ( + + {content}: {message} + + ); + }; +}); + +rs.mock('node-local-remote/test', () => ({ + default: 'module from node-local-remote (mock)', +})); + +test('renders main-app with mocked federated remotes', async () => { + render(); + + expect( + screen.getByText( + 'Open Dev Tool And Focus On Network,checkout resources details', + ), + ).toBeInTheDocument(); + + expect(screen.getByTestId('mock-button')).toBeInTheDocument(); + + expect(screen.getByTestId('mock-tooltip')).toHaveTextContent( + 'hover me please: Hello,world!', + ); + + expect(screen.getByText('Node-local remote:')).toBeInTheDocument(); + expect( + screen.getByText('module from node-local-remote (mock)'), + ).toBeInTheDocument(); +}); diff --git a/packages/core/src/core/plugins/federation.ts b/packages/core/src/core/plugins/federation.ts index 36b216c33..a50628ed8 100644 --- a/packages/core/src/core/plugins/federation.ts +++ b/packages/core/src/core/plugins/federation.ts @@ -1,44 +1,6 @@ -import type { RsbuildPlugin, Rspack } from '@rsbuild/core'; +import type { RsbuildPlugin } from '@rsbuild/core'; import type { RstestContext } from '../../types'; -function patchFederationPluginOptions(config: Rspack.Configuration) { - const plugins = config.plugins; - if (!Array.isArray(plugins)) return; - - for (const plugin of plugins) { - // `@module-federation/enhanced/rspack` exposes its options on a private field - // when used with Rspack. We avoid importing the package here and instead - // patch the shape that the plugin instance uses at runtime. - const obj = plugin as unknown as { _options?: unknown; options?: unknown }; - const opts = - plugin && typeof plugin === 'object' - ? (obj._options ?? obj.options) - : null; - - if (!opts || typeof opts !== 'object') continue; - - // Heuristic: MF plugin always has `name` plus `remotes`/`exposes`/`shared`. - if (!('name' in opts) || (!('remotes' in opts) && !('exposes' in opts))) { - continue; - } - - const shared = (opts as any).shared; - if (!shared || typeof shared !== 'object') continue; - - // MF's runtime uses `loadShareSync` for initial consumes; if a shared module - // is not eager, MF may generate an async fallback chunk which then crashes - // in Node with RUNTIME-006. Default shared items to eager unless explicitly - // set by the user. - for (const key of Object.keys(shared)) { - const val = shared[key]; - if (!val || typeof val !== 'object') continue; - if (val.eager == null) { - val.eager = true; - } - } - } -} - export const pluginFederationCompat: (context: RstestContext) => RsbuildPlugin = (context) => ({ name: 'rstest:federation-compat', @@ -59,7 +21,8 @@ export const pluginFederationCompat: (context: RstestContext) => RsbuildPlugin = config.optimization ??= {}; config.optimization.splitChunks = false; - patchFederationPluginOptions(config); + // Do not patch Module Federation plugin options. Users should configure + // shared/consumes behavior explicitly in their project configs. }); }, }); From 08cd6eec811f3f18dd5e8f5ed919fdc50ad48e3b Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 13:08:54 -0800 Subject: [PATCH 17/85] chore: clean up gitignore by removing test files --- .gitignore | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 452e11e00..9b15fe846 100644 --- a/.gitignore +++ b/.gitignore @@ -44,8 +44,4 @@ fixtures-test-*/ tests-dist/ .vscode-test/ packages/vscode/*.vsix -packages/vscode/icon.png -examples/federation/main-app/test/app-ssr.test.ts -examples/federation/main-app/test/component-remotes.dynamic.test.ts -examples/federation/main-app/test/node-local.dynamic.test.ts -examples/federation/main-app/test/node-local.static.test.ts +packages/vscode/icon.png \ No newline at end of file From d4da32743c5c026738dbf165cce1c3f939c82143 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 13:16:33 -0800 Subject: [PATCH 18/85] federation(main-app): RTL test with dynamic import, upgrade examples to react@19, configure node-local-remote via absolute commonjs path, start web+node remotes in setup; core: remove MF option patching and rely on explicit shared config --- .../federation/component-app/package.json | 5 +- examples/federation/main-app/package.json | 4 +- examples/federation/main-app/rstest.config.ts | 143 +++++++++++------- .../main-app/scripts/rstest.setup.ts | 21 ++- .../federation/main-app/test/App.rtl.test.jsx | 55 +------ pnpm-lock.yaml | 119 +++------------ 6 files changed, 133 insertions(+), 214 deletions(-) diff --git a/examples/federation/component-app/package.json b/examples/federation/component-app/package.json index a55d6f4e9..aa5d2efe2 100644 --- a/examples/federation/component-app/package.json +++ b/examples/federation/component-app/package.json @@ -21,7 +21,8 @@ "serve": "14.2.3" }, "dependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "@module-federation/node": "^2.7.26", + "react": "19.2.3", + "react-dom": "19.2.3" } } diff --git a/examples/federation/main-app/package.json b/examples/federation/main-app/package.json index 78f32826c..9e25846de 100644 --- a/examples/federation/main-app/package.json +++ b/examples/federation/main-app/package.json @@ -10,8 +10,8 @@ "test": "rstest --reporter=verbose" }, "dependencies": { - "react": "17.0.2", - "react-dom": "17.0.2" + "react": "19.2.3", + "react-dom": "19.2.3" }, "keywords": [], "author": "", diff --git a/examples/federation/main-app/rstest.config.ts b/examples/federation/main-app/rstest.config.ts index 8e1a5e9bc..5d1f07b0e 100644 --- a/examples/federation/main-app/rstest.config.ts +++ b/examples/federation/main-app/rstest.config.ts @@ -3,61 +3,94 @@ import { ModuleFederationPlugin } from '@module-federation/enhanced/rspack'; import { pluginReact } from '@rsbuild/plugin-react'; import { defineConfig } from '@rstest/core'; export default defineConfig({ - testEnvironment: 'node', - plugins: [pluginReact()], globalSetup: ['./scripts/rstestGlobalSetup.ts'], - federation: true, - // Module Federation's Node runtime may load chunks via `fs` when running in Node. - // Ensure the test build output is written to disk so those chunks exist. - dev: { - writeToDisk: true, - }, - output: { - // Module Federation's Node runtime works best with CJS output in our test runner. - // This also ensures `__rstest_dynamic_import__` is injected as a function argument - // rather than relying on ESM `import.meta` shims. - module: false, - }, - tools: { - // Enable Rspack-level customization so federated imports like `component-app/Button` - // can be handled by the Module Federation runtime. - rspack: (config) => { - config.output = { - ...(config.output ?? {}), - // Avoid hard-coding dev-server URLs for test builds. - publicPath: 'auto', - }; - (config as any).builtins ??= {} as any; - (config as any).builtins.define = { - ...(((config as any).builtins.define as any) ?? {}), - __NODE_LOCAL_REMOTE__: 'true', - } as any; - - config.plugins ??= []; - const nodeLocalEntry = path.resolve( - __dirname, - '../node-local-remote/dist-node/remoteEntry.js', - ); - - config.plugins.push( - new ModuleFederationPlugin({ - name: 'main_app', - library: { type: 'commonjs-module', name: 'main_app' }, - remoteType: 'script', - remotes: { - 'component-app': - 'component_app@http://localhost:3003/remoteEntry.js', - 'node-local-remote': `commonjs ${nodeLocalEntry}`, - }, - runtimePlugins: ['@module-federation/node/runtimePlugin'], - shared: { - react: { singleton: true, requiredVersion: '19.2.3' }, - 'react-dom': { singleton: true, requiredVersion: '19.2.3' }, - }, - }), - ); - - return config; + projects: [ + { + name: 'main-app-node', + testEnvironment: 'node', + plugins: [pluginReact()], + federation: true, + dev: { writeToDisk: true }, + output: { module: false }, + tools: { + rspack: (config) => { + config.output = { ...(config.output ?? {}), publicPath: 'auto' }; + (config as any).builtins ??= {} as any; + (config as any).builtins.define = { + ...(((config as any).builtins.define as any) ?? {}), + __NODE_LOCAL_REMOTE__: 'true', + } as any; + config.plugins ??= []; + const nodeLocalEntryAbs = path.resolve( + __dirname, + '../node-local-remote/dist-node/remoteEntry.js', + ); + config.plugins.push( + new ModuleFederationPlugin({ + name: 'main_app_node', + library: { type: 'commonjs-module', name: 'main_app_node' }, + remoteType: 'script', + remotes: { + 'component-app': + 'component_app@http://localhost:3003/remoteEntry.js', + 'node-local-remote': `commonjs ${nodeLocalEntryAbs}`, + }, + runtimePlugins: ['@module-federation/node/runtimePlugin'], + shared: { + react: { + singleton: true, + eager: true, + requiredVersion: '19.2.3', + }, + 'react-dom': { + singleton: true, + eager: true, + requiredVersion: '19.2.3', + }, + }, + }), + ); + return config; + }, + }, }, - }, + { + name: 'main-app-jsdom', + testEnvironment: 'jsdom', + plugins: [pluginReact()], + federation: true, + tools: { + rspack: (config) => { + config.output = { ...(config.output ?? {}), publicPath: 'auto' }; + config.plugins ??= []; + config.plugins.push( + new ModuleFederationPlugin({ + name: 'main_app_web', + remoteType: 'script', + remotes: { + 'component-app': + 'component_app@http://localhost:3001/remoteEntry.js', + 'node-local-remote': + 'node_local_remote@http://localhost:3004/remoteEntry.js', + }, + shared: { + react: { + singleton: true, + eager: true, + requiredVersion: '19.2.3', + }, + 'react-dom': { + singleton: true, + eager: true, + requiredVersion: '19.2.3', + }, + }, + }), + ); + return config; + }, + }, + include: ['test/**/*.rtl.*'], + }, + ], }); diff --git a/examples/federation/main-app/scripts/rstest.setup.ts b/examples/federation/main-app/scripts/rstest.setup.ts index 75809f283..d3e65ca1b 100644 --- a/examples/federation/main-app/scripts/rstest.setup.ts +++ b/examples/federation/main-app/scripts/rstest.setup.ts @@ -106,16 +106,25 @@ const ensureNodeRemoteImpl = async () => { } // Owner path: build, serve, wait. + void killPort(3001).catch(() => {}); void killPort(3003).catch(() => {}); - await run(componentAppDir, 'npx', ['pnpm', 'build:node']); + void killPort(3004).catch(() => {}); + await run(componentAppDir, 'pnpm', ['build:node']); + await run(componentAppDir, 'pnpm', ['build']); globalThis.__RSTEST_MF_CHILDREN__.push( - start('component-app(node)', componentAppDir, 'npx', [ - 'pnpm', - 'serve:node', - ]), + start('component-app(node)', componentAppDir, 'pnpm', ['serve:node']), + ); + globalThis.__RSTEST_MF_CHILDREN__.push( + start('component-app(web)', componentAppDir, 'pnpm', ['serve']), ); await waitForUrl(remoteEntryUrl); - await run(nodeLocalDir, 'npx', ['pnpm', 'build:node']); + await run(nodeLocalDir, 'pnpm', ['build:node']); + await run(nodeLocalDir, 'pnpm', ['build']); + globalThis.__RSTEST_MF_CHILDREN__.push( + start('node-local-remote(web)', nodeLocalDir, 'pnpm', ['serve']), + ); + await waitForUrl('http://localhost:3001/remoteEntry.js'); + await waitForUrl('http://localhost:3004/remoteEntry.js'); }; declare global { diff --git a/examples/federation/main-app/test/App.rtl.test.jsx b/examples/federation/main-app/test/App.rtl.test.jsx index 1387f0fa2..1a1af72b6 100644 --- a/examples/federation/main-app/test/App.rtl.test.jsx +++ b/examples/federation/main-app/test/App.rtl.test.jsx @@ -1,47 +1,10 @@ -import { expect, rs, test } from '@rstest/core'; +import { expect, test } from '@rstest/core'; import { render, screen } from '@testing-library/react'; -import App from '../App.jsx'; -rs.mock('component-app/Button', () => { - return function Button() { - return ( - - ); - }; -}); - -rs.mock('component-app/Dialog', () => { - return function Dialog({ visible, switchVisible }) { - return ( -
- -
- ); - }; -}); - -rs.mock('component-app/ToolTip', () => { - return function ToolTip({ content, message }) { - return ( - - {content}: {message} - - ); - }; -}); - -rs.mock('node-local-remote/test', () => ({ - default: 'module from node-local-remote (mock)', -})); +// dynamic import to avoid eager consumption of federated remotes -test('renders main-app with mocked federated remotes', async () => { +test('renders main-app with federated remotes', async () => { + const { default: App } = await import('../App.jsx'); render(); expect( @@ -50,14 +13,10 @@ test('renders main-app with mocked federated remotes', async () => { ), ).toBeInTheDocument(); - expect(screen.getByTestId('mock-button')).toBeInTheDocument(); + expect(screen.getByText(/Buttons:/i)).toBeInTheDocument(); - expect(screen.getByTestId('mock-tooltip')).toHaveTextContent( - 'hover me please: Hello,world!', - ); + expect(screen.getByText(/hover me please/i)).toBeInTheDocument(); expect(screen.getByText('Node-local remote:')).toBeInTheDocument(); - expect( - screen.getByText('module from node-local-remote (mock)'), - ).toBeInTheDocument(); + expect(screen.getByText('module from node-local-remote')).toBeInTheDocument(); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 93ade77ba..0557f79b0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -472,16 +472,19 @@ importers: examples/federation/component-app: dependencies: + '@module-federation/node': + specifier: ^2.7.26 + version: 2.7.26(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) react: - specifier: ^17.0.2 - version: 17.0.2 + specifier: 19.2.3 + version: 19.2.3 react-dom: - specifier: ^17.0.2 - version: 17.0.2(react@17.0.2) + specifier: 19.2.3 + version: 19.2.3(react@19.2.3) devDependencies: '@module-federation/enhanced': specifier: 0.22.0 - version: 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + version: 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) '@rspack/cli': specifier: 1.6.8 version: 1.6.8(@rspack/core@1.6.8(@swc/helpers@0.5.18))(@types/express@4.17.25)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) @@ -498,18 +501,18 @@ importers: examples/federation/main-app: dependencies: react: - specifier: 17.0.2 - version: 17.0.2 + specifier: 19.2.3 + version: 19.2.3 react-dom: - specifier: 17.0.2 - version: 17.0.2(react@17.0.2) + specifier: 19.2.3 + version: 19.2.3(react@19.2.3) devDependencies: '@module-federation/enhanced': specifier: 0.22.0 - version: 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + version: 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) '@module-federation/node': specifier: ^2.7.26 - version: 2.7.26(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) + version: 2.7.26(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) '@rsbuild/plugin-react': specifier: ^1.4.2 version: 1.4.2(@rsbuild/core@1.7.1) @@ -524,7 +527,7 @@ importers: version: link:../../../packages/core '@testing-library/react': specifier: 14.0.0 - version: 14.0.0(@types/react@19.2.7)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + version: 14.0.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) concurrently: specifier: 8.2.2 version: 8.2.2 @@ -6874,11 +6877,6 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - react-dom@17.0.2: - resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} - peerDependencies: - react: 17.0.2 - react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: @@ -6938,10 +6936,6 @@ packages: react-dom: optional: true - react@17.0.2: - resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==} - engines: {node: '>=0.10.0'} - react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -7314,9 +7308,6 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} - scheduler@0.20.2: - resolution: {integrity: sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==} - scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} @@ -9409,14 +9400,6 @@ snapshots: - utf-8-validate - vue-tsc - '@module-federation/data-prefetch@0.22.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': - dependencies: - '@module-federation/runtime': 0.22.0 - '@module-federation/sdk': 0.22.0 - fs-extra: 9.1.0 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - '@module-federation/data-prefetch@0.22.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@module-federation/runtime': 0.22.0 @@ -9450,34 +9433,6 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/enhanced@0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)))': - dependencies: - '@module-federation/bridge-react-webpack-plugin': 0.22.0 - '@module-federation/cli': 0.22.0(typescript@5.9.3) - '@module-federation/data-prefetch': 0.22.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@module-federation/dts-plugin': 0.22.0(typescript@5.9.3) - '@module-federation/error-codes': 0.22.0 - '@module-federation/inject-external-runtime-core-plugin': 0.22.0(@module-federation/runtime-tools@0.22.0) - '@module-federation/managers': 0.22.0 - '@module-federation/manifest': 0.22.0(typescript@5.9.3) - '@module-federation/rspack': 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(typescript@5.9.3) - '@module-federation/runtime-tools': 0.22.0 - '@module-federation/sdk': 0.22.0 - btoa: 1.2.1 - schema-utils: 4.3.3 - upath: 2.0.1 - optionalDependencies: - typescript: 5.9.3 - webpack: 5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)) - transitivePeerDependencies: - - '@rspack/core' - - bufferutil - - debug - - react - - react-dom - - supports-color - - utf-8-validate - '@module-federation/enhanced@0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)))': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.22.0 @@ -9535,27 +9490,6 @@ snapshots: - utf-8-validate - vue-tsc - '@module-federation/node@2.7.26(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)))': - dependencies: - '@module-federation/enhanced': 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) - '@module-federation/runtime': 0.22.0 - '@module-federation/sdk': 0.22.0 - btoa: 1.2.1 - encoding: 0.1.13 - node-fetch: 2.7.0(encoding@0.1.13) - webpack: 5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)) - optionalDependencies: - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - transitivePeerDependencies: - - '@rspack/core' - - bufferutil - - debug - - supports-color - - typescript - - utf-8-validate - - vue-tsc - '@module-federation/node@2.7.26(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18)))': dependencies: '@module-federation/enhanced': 0.22.0(@rspack/core@1.6.8(@swc/helpers@0.5.18))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.7(@swc/helpers@0.5.18))) @@ -10873,13 +10807,13 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/react@14.0.0(@types/react@19.2.7)(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@testing-library/react@14.0.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@babel/runtime': 7.26.9 '@testing-library/dom': 9.3.4 '@types/react-dom': 18.3.7(@types/react@19.2.7) - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) transitivePeerDependencies: - '@types/react' @@ -15629,13 +15563,6 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - react-dom@17.0.2(react@17.0.2): - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react: 17.0.2 - scheduler: 0.20.2 - react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 @@ -15686,11 +15613,6 @@ snapshots: optionalDependencies: react-dom: 19.2.3(react@19.2.3) - react@17.0.2: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -16090,11 +16012,6 @@ snapshots: dependencies: xmlchars: 2.2.0 - scheduler@0.20.2: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - scheduler@0.23.2: dependencies: loose-envify: 1.4.0 From 576cfa1871eff0dea7df16f97dda55df9de83906 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 13:32:22 -0800 Subject: [PATCH 19/85] fix(federation): stabilize example setup --- examples/federation/main-app/package.json | 2 +- examples/federation/main-app/rstest.config.ts | 8 +- .../main-app/scripts/rstest.setup.ts | 36 ++- pnpm-lock.yaml | 272 +----------------- 4 files changed, 31 insertions(+), 287 deletions(-) diff --git a/examples/federation/main-app/package.json b/examples/federation/main-app/package.json index 9e25846de..66bc80d5b 100644 --- a/examples/federation/main-app/package.json +++ b/examples/federation/main-app/package.json @@ -23,7 +23,7 @@ "@rsbuild/plugin-react": "^1.4.2", "@rspack/cli": "1.6.8", "@rspack/core": "1.6.8", - "@testing-library/react": "14.0.0", + "@testing-library/react": "16.3.1", "kill-port": "^2.0.1", "concurrently": "8.2.2", "serve": "14.2.3" diff --git a/examples/federation/main-app/rstest.config.ts b/examples/federation/main-app/rstest.config.ts index 5d1f07b0e..3032d6325 100644 --- a/examples/federation/main-app/rstest.config.ts +++ b/examples/federation/main-app/rstest.config.ts @@ -4,12 +4,14 @@ import { pluginReact } from '@rsbuild/plugin-react'; import { defineConfig } from '@rstest/core'; export default defineConfig({ globalSetup: ['./scripts/rstestGlobalSetup.ts'], + testTimeout: 15000, projects: [ { name: 'main-app-node', testEnvironment: 'node', plugins: [pluginReact()], federation: true, + exclude: ['test/**/*.rtl.*'], dev: { writeToDisk: true }, output: { module: false }, tools: { @@ -70,8 +72,10 @@ export default defineConfig({ remotes: { 'component-app': 'component_app@http://localhost:3001/remoteEntry.js', - 'node-local-remote': - 'node_local_remote@http://localhost:3004/remoteEntry.js', + 'node-local-remote': `commonjs ${path.resolve( + __dirname, + '../node-local-remote/dist-node/remoteEntry.js', + )}`, }, shared: { react: { diff --git a/examples/federation/main-app/scripts/rstest.setup.ts b/examples/federation/main-app/scripts/rstest.setup.ts index d3e65ca1b..59c17d55f 100644 --- a/examples/federation/main-app/scripts/rstest.setup.ts +++ b/examples/federation/main-app/scripts/rstest.setup.ts @@ -85,8 +85,13 @@ const waitForUrl = async ( }; const ensureNodeRemoteImpl = async () => { - // Fast path if already reachable. - if (await isUrlReachable(remoteEntryUrl, 500)) return; + const need3003 = !(await isUrlReachable(remoteEntryUrl, 500)); + const need3001 = !(await isUrlReachable( + 'http://localhost:3001/remoteEntry.js', + 500, + )); + + if (!need3003 && !need3001) return; // Try to become the owner (cross-worker). let fd: number | null = null; @@ -95,9 +100,10 @@ const ensureNodeRemoteImpl = async () => { globalThis.__RSTEST_MF_OWNER__ = true; } catch (e: any) { if (e?.code === 'EEXIST') { - // Another worker is (supposedly) starting it; wait, but allow stale lock recovery. + // Another worker is (supposedly) starting it; wait for all pending endpoints. globalThis.__RSTEST_MF_OWNER__ = false; - await waitForUrl(remoteEntryUrl); + if (need3003) await waitForUrl(remoteEntryUrl); + if (need3001) await waitForUrl('http://localhost:3001/remoteEntry.js'); return; } throw e; @@ -105,26 +111,28 @@ const ensureNodeRemoteImpl = async () => { if (fd !== null) closeSync(fd); } - // Owner path: build, serve, wait. - void killPort(3001).catch(() => {}); - void killPort(3003).catch(() => {}); - void killPort(3004).catch(() => {}); + // Owner path: build required outputs, start servers, then wait for all endpoints. + await killPort(3001).catch(() => {}); + await killPort(3003).catch(() => {}); + + // Build local commonjs remote first so path-based require works for node tests + await run(nodeLocalDir, 'pnpm', ['build:node']); + await run(nodeLocalDir, 'pnpm', ['build']); + + // Build component app for both node and web await run(componentAppDir, 'pnpm', ['build:node']); await run(componentAppDir, 'pnpm', ['build']); + + // Start servers globalThis.__RSTEST_MF_CHILDREN__.push( start('component-app(node)', componentAppDir, 'pnpm', ['serve:node']), ); globalThis.__RSTEST_MF_CHILDREN__.push( start('component-app(web)', componentAppDir, 'pnpm', ['serve']), ); + // Wait for endpoints await waitForUrl(remoteEntryUrl); - await run(nodeLocalDir, 'pnpm', ['build:node']); - await run(nodeLocalDir, 'pnpm', ['build']); - globalThis.__RSTEST_MF_CHILDREN__.push( - start('node-local-remote(web)', nodeLocalDir, 'pnpm', ['serve']), - ); await waitForUrl('http://localhost:3001/remoteEntry.js'); - await waitForUrl('http://localhost:3004/remoteEntry.js'); }; declare global { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0557f79b0..60ee157ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -526,8 +526,8 @@ importers: specifier: workspace:* version: link:../../../packages/core '@testing-library/react': - specifier: 14.0.0 - version: 14.0.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + specifier: 16.3.1 + version: 16.3.1(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) concurrently: specifier: 8.2.2 version: 8.2.2 @@ -2939,21 +2939,10 @@ packages: resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} - '@testing-library/dom@9.3.4': - resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==} - engines: {node: '>=14'} - '@testing-library/jest-dom@6.9.1': resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} - '@testing-library/react@14.0.0': - resolution: {integrity: sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==} - engines: {node: '>=14'} - peerDependencies: - react: ^18.0.0 - react-dom: ^18.0.0 - '@testing-library/react@16.3.1': resolution: {integrity: sha512-gr4KtAWqIOQoucWYD/f6ki+j5chXfcPc74Col/6poTyqTmn7zRmodWahWRCp8tYd+GMqBonw6hstNzqjbs6gjw==} engines: {node: '>=18'} @@ -3583,16 +3572,9 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - aria-query@5.1.3: - resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} - aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - array-buffer-byte-length@1.0.2: - resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} - engines: {node: '>= 0.4'} - array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} @@ -4233,10 +4215,6 @@ packages: deep-equal@1.0.1: resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==} - deep-equal@2.2.3: - resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} - engines: {node: '>= 0.4'} - deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -4501,9 +4479,6 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-get-iterator@1.1.3: - resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} - es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} @@ -4803,9 +4778,6 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - generator-function@2.0.1: resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} engines: {node: '>= 0.4'} @@ -4921,10 +4893,6 @@ packages: resolution: {integrity: sha512-QsCdAUHAmiDeKeaNojb1OHOPF7NjcWPBR7obdu3NwH2a/oyQaLg5d0aaCy/9My6CdPChYF07dvz5chaXBGaD4g==} engines: {node: '>=20.0.0'} - has-bigints@1.1.0: - resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} - engines: {node: '>= 0.4'} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -5158,10 +5126,6 @@ packages: inline-style-parser@0.2.4: resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} - internal-slot@1.1.0: - resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} - engines: {node: '>= 0.4'} - ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -5184,25 +5148,13 @@ packages: resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} engines: {node: '>= 0.4'} - is-array-buffer@3.0.5: - resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} - engines: {node: '>= 0.4'} - is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-bigint@1.1.0: - resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} - engines: {node: '>= 0.4'} - is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - is-boolean-object@1.2.2: - resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} - engines: {node: '>= 0.4'} - is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -5215,10 +5167,6 @@ packages: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} - is-date-object@1.1.0: - resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} - engines: {node: '>= 0.4'} - is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} @@ -5272,10 +5220,6 @@ packages: resolution: {integrity: sha512-AX2uU0HW+TxagTgQXOJY7+2fbFHemC7YFBwN1XqD8qQMKdtfbOC8OC3fUb4s5NU59a3662Dzwto8tWDdZYRXxg==} engines: {node: '>=12'} - is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - is-nan@1.3.2: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} @@ -5284,10 +5228,6 @@ packages: resolution: {integrity: sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==} engines: {node: '>=16'} - is-number-object@1.1.1: - resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} - engines: {node: '>= 0.4'} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -5327,30 +5267,14 @@ packages: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} - is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - - is-shared-array-buffer@1.0.4: - resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} - engines: {node: '>= 0.4'} - is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - is-string@1.1.1: - resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} - engines: {node: '>= 0.4'} - is-subdir@1.2.0: resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} engines: {node: '>=4'} - is-symbol@1.1.1: - resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} - engines: {node: '>= 0.4'} - is-typed-array@1.1.15: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} @@ -5370,14 +5294,6 @@ packages: is-url@1.2.4: resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} - is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - - is-weakset@2.0.4: - resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} - engines: {node: '>= 0.4'} - is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -7009,10 +6925,6 @@ packages: regex@6.0.1: resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==} - regexp.prototype.flags@1.5.4: - resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} - engines: {node: '>= 0.4'} - registry-auth-token@3.3.2: resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==} @@ -7393,10 +7305,6 @@ packages: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} - set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - set-value@4.1.0: resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==} engines: {node: '>=11.0'} @@ -7592,10 +7500,6 @@ packages: resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} engines: {node: '>=18'} - stop-iteration-iterator@1.1.0: - resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} - engines: {node: '>= 0.4'} - stream-browserify@3.0.0: resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} @@ -8225,14 +8129,6 @@ packages: whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - which-boxed-primitive@1.1.1: - resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} - engines: {node: '>= 0.4'} - - which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - which-typed-array@1.1.19: resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} engines: {node: '>= 0.4'} @@ -10787,17 +10683,6 @@ snapshots: picocolors: 1.1.1 pretty-format: 27.5.1 - '@testing-library/dom@9.3.4': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/runtime': 7.26.9 - '@types/aria-query': 5.0.4 - aria-query: 5.1.3 - chalk: 4.1.2 - dom-accessibility-api: 0.5.16 - lz-string: 1.5.0 - pretty-format: 27.5.1 - '@testing-library/jest-dom@6.9.1': dependencies: '@adobe/css-tools': 4.4.4 @@ -10807,16 +10692,6 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/react@14.0.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@babel/runtime': 7.26.9 - '@testing-library/dom': 9.3.4 - '@types/react-dom': 18.3.7(@types/react@19.2.7) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - transitivePeerDependencies: - - '@types/react' - '@testing-library/react@16.3.1(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.27))(@types/react@18.3.27)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.9 @@ -11071,10 +10946,6 @@ snapshots: dependencies: '@types/react': 18.3.27 - '@types/react-dom@18.3.7(@types/react@19.2.7)': - dependencies: - '@types/react': 19.2.7 - '@types/react-dom@19.2.3(@types/react@19.2.7)': dependencies: '@types/react': 19.2.7 @@ -11670,19 +11541,10 @@ snapshots: argparse@2.0.1: {} - aria-query@5.1.3: - dependencies: - deep-equal: 2.2.3 - aria-query@5.3.0: dependencies: dequal: 2.0.3 - array-buffer-byte-length@1.0.2: - dependencies: - call-bound: 1.0.4 - is-array-buffer: 3.0.5 - array-flatten@1.1.1: {} array-union@2.1.0: {} @@ -12369,27 +12231,6 @@ snapshots: deep-equal@1.0.1: {} - deep-equal@2.2.3: - dependencies: - array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 - es-get-iterator: 1.1.3 - get-intrinsic: 1.3.0 - is-arguments: 1.2.0 - is-array-buffer: 3.0.5 - is-date-object: 1.1.0 - is-regex: 1.2.1 - is-shared-array-buffer: 1.0.4 - isarray: 2.0.5 - object-is: 1.1.6 - object-keys: 1.1.1 - object.assign: 4.1.7 - regexp.prototype.flags: 1.5.4 - side-channel: 1.1.0 - which-boxed-primitive: 1.1.1 - which-collection: 1.0.2 - which-typed-array: 1.1.19 - deep-extend@0.6.0: {} deepmerge@4.3.1: {} @@ -12639,18 +12480,6 @@ snapshots: es-errors@1.3.0: {} - es-get-iterator@1.1.3: - dependencies: - call-bind: 1.0.8 - get-intrinsic: 1.3.0 - has-symbols: 1.1.0 - is-arguments: 1.2.0 - is-map: 2.0.3 - is-set: 2.0.3 - is-string: 1.1.1 - isarray: 2.0.5 - stop-iteration-iterator: 1.1.0 - es-module-lexer@1.7.0: {} es-object-atoms@1.1.1: @@ -12982,8 +12811,6 @@ snapshots: function-bind@1.1.2: {} - functions-have-names@1.2.3: {} - generator-function@2.0.1: {} gensync@1.0.0-beta.2: {} @@ -13115,8 +12942,6 @@ snapshots: '@types/whatwg-mimetype': 3.0.2 whatwg-mimetype: 3.0.0 - has-bigints@1.1.0: {} - has-flag@4.0.0: {} has-property-descriptors@1.0.2: @@ -13448,12 +13273,6 @@ snapshots: inline-style-parser@0.2.4: {} - internal-slot@1.1.0: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 - ipaddr.js@1.9.1: {} ipaddr.js@2.3.0: {} @@ -13472,27 +13291,12 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 - is-array-buffer@3.0.5: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - is-arrayish@0.2.1: {} - is-bigint@1.1.0: - dependencies: - has-bigints: 1.1.0 - is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 - is-boolean-object@1.2.2: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - is-callable@1.2.7: {} is-ci@2.0.0: @@ -13503,11 +13307,6 @@ snapshots: dependencies: hasown: 2.0.2 - is-date-object@1.1.0: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - is-decimal@2.0.1: {} is-docker@2.2.1: {} @@ -13546,8 +13345,6 @@ snapshots: dependencies: globalthis: 1.0.4 - is-map@2.0.3: {} - is-nan@1.3.2: dependencies: call-bind: 1.0.8 @@ -13555,11 +13352,6 @@ snapshots: is-network-error@1.3.0: {} - is-number-object@1.1.1: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - is-number@7.0.0: {} is-path-inside@3.0.3: {} @@ -13587,29 +13379,12 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 - is-set@2.0.3: {} - - is-shared-array-buffer@1.0.4: - dependencies: - call-bound: 1.0.4 - is-stream@2.0.1: {} - is-string@1.1.1: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - is-subdir@1.2.0: dependencies: better-path-resolve: 1.0.0 - is-symbol@1.1.1: - dependencies: - call-bound: 1.0.4 - has-symbols: 1.1.0 - safe-regex-test: 1.1.0 - is-typed-array@1.1.15: dependencies: which-typed-array: 1.1.19 @@ -13622,13 +13397,6 @@ snapshots: is-url@1.2.4: {} - is-weakmap@2.0.2: {} - - is-weakset@2.0.4: - dependencies: - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - is-windows@1.0.2: {} is-wsl@2.2.0: @@ -15719,15 +15487,6 @@ snapshots: dependencies: regex-utilities: 2.3.0 - regexp.prototype.flags@1.5.4: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-errors: 1.3.0 - get-proto: 1.0.1 - gopd: 1.2.0 - set-function-name: 2.0.2 - registry-auth-token@3.3.2: dependencies: rc: 1.2.8 @@ -16150,13 +15909,6 @@ snapshots: gopd: 1.2.0 has-property-descriptors: 1.0.2 - set-function-name@2.0.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - set-value@4.1.0: dependencies: is-plain-object: 2.0.4 @@ -16393,11 +16145,6 @@ snapshots: stdin-discarder@0.2.2: {} - stop-iteration-iterator@1.1.0: - dependencies: - es-errors: 1.3.0 - internal-slot: 1.1.0 - stream-browserify@3.0.0: dependencies: inherits: 2.0.4 @@ -17056,21 +16803,6 @@ snapshots: tr46: 0.0.3 webidl-conversions: 3.0.1 - which-boxed-primitive@1.1.1: - dependencies: - is-bigint: 1.1.0 - is-boolean-object: 1.2.2 - is-number-object: 1.1.1 - is-string: 1.1.1 - is-symbol: 1.1.1 - - which-collection@1.0.2: - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.4 - which-typed-array@1.1.19: dependencies: available-typed-arrays: 1.0.7 From fb5b55c1413a1200f2a939fc838a932e20037752 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 13:44:15 -0800 Subject: [PATCH 20/85] examples(federation): rename browser configs to rspack.browser.config.js and update scripts --- .../federation/component-app/package.json | 2 +- ...ack.config.js => rspack.browser.config.js} | 21 ++++------------ examples/federation/main-app/package.json | 2 +- ...ack.config.js => rspack.browser.config.js} | 24 ++++--------------- .../federation/node-local-remote/package.json | 2 +- ...ack.config.js => rspack.browser.config.js} | 4 +--- 6 files changed, 13 insertions(+), 42 deletions(-) rename examples/federation/component-app/{rspack.config.js => rspack.browser.config.js} (71%) rename examples/federation/main-app/{rspack.config.js => rspack.browser.config.js} (63%) rename examples/federation/node-local-remote/{rspack.config.js => rspack.browser.config.js} (88%) diff --git a/examples/federation/component-app/package.json b/examples/federation/component-app/package.json index aa5d2efe2..d6e01c47e 100644 --- a/examples/federation/component-app/package.json +++ b/examples/federation/component-app/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "build": "rspack build --config rspack.config.js ", + "build": "rspack build --config rspack.browser.config.js ", "build:node": "rspack build --config rspack.node.config.js", "serve": "serve dist -p 3001", "serve:node": "serve dist-node -p 3003", diff --git a/examples/federation/component-app/rspack.config.js b/examples/federation/component-app/rspack.browser.config.js similarity index 71% rename from examples/federation/component-app/rspack.config.js rename to examples/federation/component-app/rspack.browser.config.js index 3b862d90e..e53d65854 100644 --- a/examples/federation/component-app/rspack.config.js +++ b/examples/federation/component-app/rspack.browser.config.js @@ -19,32 +19,21 @@ module.exports = { }, module: { rules: [ - { - test: /\.(jpg|png|gif|jpeg)$/, - type: 'asset/resource', - }, + { test: /\.(jpg|png|gif|jpeg)$/, type: 'asset/resource' }, { test: /\.(js|jsx)$/, use: { loader: 'builtin:swc-loader', options: { jsc: { - parser: { - syntax: 'ecmascript', - jsx: true, - }, - transform: { - react: { - runtime: 'automatic', - }, - }, + parser: { syntax: 'ecmascript', jsx: true }, + transform: { react: { runtime: 'automatic' } }, }, }, }, }, ], }, - plugins: [ new ModuleFederationPlugin({ name: 'component_app', @@ -57,8 +46,6 @@ module.exports = { './ToolTip': './src/ToolTip.jsx', }, }), - new HtmlRspackPlugin({ - template: './public/index.html', - }), + new HtmlRspackPlugin({ template: './public/index.html' }), ], }; diff --git a/examples/federation/main-app/package.json b/examples/federation/main-app/package.json index 66bc80d5b..96e26eb5b 100644 --- a/examples/federation/main-app/package.json +++ b/examples/federation/main-app/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "build": "rspack build --config rspack.config.js", + "build": "rspack build --config rspack.browser.config.js", "serve": "serve dist -p 3002", "start": "concurrently \"npm run build\" \"npm run serve\"", "test": "rstest --reporter=verbose" diff --git a/examples/federation/main-app/rspack.config.js b/examples/federation/main-app/rspack.browser.config.js similarity index 63% rename from examples/federation/main-app/rspack.config.js rename to examples/federation/main-app/rspack.browser.config.js index 900dc2853..bb0a9d7ae 100644 --- a/examples/federation/main-app/rspack.config.js +++ b/examples/federation/main-app/rspack.browser.config.js @@ -13,25 +13,15 @@ module.exports = { }, module: { rules: [ - { - test: /\.(jpg|png|gif|jpeg)$/, - type: 'asset/resource', - }, + { test: /\.(jpg|png|gif|jpeg)$/, type: 'asset/resource' }, { test: /\.(js|jsx)$/, use: { loader: 'builtin:swc-loader', options: { jsc: { - parser: { - syntax: 'ecmascript', - jsx: true, - }, - transform: { - react: { - runtime: 'automatic', - }, - }, + parser: { syntax: 'ecmascript', jsx: true }, + transform: { react: { runtime: 'automatic' } }, }, }, }, @@ -47,11 +37,7 @@ module.exports = { 'node_local_remote@http://localhost:3004/remoteEntry.js', }, }), - new DefinePlugin({ - __NODE_LOCAL_REMOTE__: JSON.stringify(true), - }), - new HtmlRspackPlugin({ - template: './public/index.html', - }), + new DefinePlugin({ __NODE_LOCAL_REMOTE__: JSON.stringify(true) }), + new HtmlRspackPlugin({ template: './public/index.html' }), ], }; diff --git a/examples/federation/node-local-remote/package.json b/examples/federation/node-local-remote/package.json index 6d3179010..0ccc6e195 100644 --- a/examples/federation/node-local-remote/package.json +++ b/examples/federation/node-local-remote/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "scripts": { - "build": "rspack build --config rspack.config.js", + "build": "rspack build --config rspack.browser.config.js", "build:node": "rspack build --config rspack.node.config.js", "serve": "serve dist -p 3004", "serve:node": "serve dist-node -p 3004" diff --git a/examples/federation/node-local-remote/rspack.config.js b/examples/federation/node-local-remote/rspack.browser.config.js similarity index 88% rename from examples/federation/node-local-remote/rspack.config.js rename to examples/federation/node-local-remote/rspack.browser.config.js index 83935ed37..112066df5 100644 --- a/examples/federation/node-local-remote/rspack.config.js +++ b/examples/federation/node-local-remote/rspack.browser.config.js @@ -16,9 +16,7 @@ module.exports = { new ModuleFederationPlugin({ name: 'node_local_remote', filename: 'remoteEntry.js', - exposes: { - './test': './src/test.js', - }, + exposes: { './test': './src/test.js' }, }), ], }; From 16ce11857675aa024d287fccb440dd4f6f5f1576 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 7 Jan 2026 15:27:26 -0800 Subject: [PATCH 21/85] examples(federation): jsdom-only rstest, remove node project; rename browser configs to rspack.browser.config.js; switch remotes to: component-app HTTP, node-local-remote commonjs path; remove __NODE_LOCAL_REMOTE__; convert tests to RTL with dynamic imports; stabilize setup to build/serve before tests --- .../component-app/rspack.browser.config.js | 2 +- examples/federation/main-app/package.json | 1 + .../main-app/rspack.browser.config.js | 3 +- .../federation/main-app/rspack.node.config.js | 2 - examples/federation/main-app/rstest.config.ts | 131 ++++++------------ .../main-app/scripts/rstest.rtl.setup.ts | 41 ++++++ .../main-app/scripts/rstest.setup.ts | 16 ++- .../federation/main-app/test/App.rtl.test.jsx | 4 +- .../federation/main-app/test/AppSsr.test.ts | 14 -- .../test/ComponentRemotes.dynamic.test.ts | 30 ---- .../test/ComponentRemotes.dynamic.test.tsx | 24 ++++ ...mic.test.ts => NodeLocal.dynamic.test.tsx} | 4 +- ...atic.test.ts => NodeLocal.static.test.tsx} | 4 +- packages/core/src/runtime/worker/env/utils.ts | 12 +- 14 files changed, 135 insertions(+), 153 deletions(-) create mode 100644 examples/federation/main-app/scripts/rstest.rtl.setup.ts delete mode 100644 examples/federation/main-app/test/AppSsr.test.ts delete mode 100644 examples/federation/main-app/test/ComponentRemotes.dynamic.test.ts create mode 100644 examples/federation/main-app/test/ComponentRemotes.dynamic.test.tsx rename examples/federation/main-app/test/{NodeLocal.dynamic.test.ts => NodeLocal.dynamic.test.tsx} (50%) rename examples/federation/main-app/test/{NodeLocal.static.test.ts => NodeLocal.static.test.tsx} (51%) diff --git a/examples/federation/component-app/rspack.browser.config.js b/examples/federation/component-app/rspack.browser.config.js index e53d65854..cb2cb7e9d 100644 --- a/examples/federation/component-app/rspack.browser.config.js +++ b/examples/federation/component-app/rspack.browser.config.js @@ -38,7 +38,7 @@ module.exports = { new ModuleFederationPlugin({ name: 'component_app', filename: 'remoteEntry.js', - library: { type: 'commonjs-module' }, + library: { type: 'var', name: 'component_app' }, exposes: { './Button': './src/Button.jsx', './Dialog': './src/Dialog.jsx', diff --git a/examples/federation/main-app/package.json b/examples/federation/main-app/package.json index 96e26eb5b..80317f756 100644 --- a/examples/federation/main-app/package.json +++ b/examples/federation/main-app/package.json @@ -7,6 +7,7 @@ "build": "rspack build --config rspack.browser.config.js", "serve": "serve dist -p 3002", "start": "concurrently \"npm run build\" \"npm run serve\"", + "pretest": "npx kill-port 3001 3003 || true", "test": "rstest --reporter=verbose" }, "dependencies": { diff --git a/examples/federation/main-app/rspack.browser.config.js b/examples/federation/main-app/rspack.browser.config.js index bb0a9d7ae..f705eabae 100644 --- a/examples/federation/main-app/rspack.browser.config.js +++ b/examples/federation/main-app/rspack.browser.config.js @@ -1,4 +1,4 @@ -const { HtmlRspackPlugin, DefinePlugin } = require('@rspack/core'); +const { HtmlRspackPlugin } = require('@rspack/core'); const { ModuleFederationPlugin, } = require('@module-federation/enhanced/rspack'); @@ -37,7 +37,6 @@ module.exports = { 'node_local_remote@http://localhost:3004/remoteEntry.js', }, }), - new DefinePlugin({ __NODE_LOCAL_REMOTE__: JSON.stringify(true) }), new HtmlRspackPlugin({ template: './public/index.html' }), ], }; diff --git a/examples/federation/main-app/rspack.node.config.js b/examples/federation/main-app/rspack.node.config.js index b127ff591..0374d97a5 100644 --- a/examples/federation/main-app/rspack.node.config.js +++ b/examples/federation/main-app/rspack.node.config.js @@ -1,7 +1,6 @@ const { ModuleFederationPlugin, } = require('@module-federation/enhanced/rspack'); -const { DefinePlugin } = require('@rspack/core'); module.exports = { entry: './index.js', @@ -47,6 +46,5 @@ module.exports = { 'react-dom': { singleton: true, requiredVersion: '19.2.3' }, }, }), - new DefinePlugin({ __NODE_LOCAL_REMOTE__: JSON.stringify(true) }), ], }; diff --git a/examples/federation/main-app/rstest.config.ts b/examples/federation/main-app/rstest.config.ts index 3032d6325..6676c304d 100644 --- a/examples/federation/main-app/rstest.config.ts +++ b/examples/federation/main-app/rstest.config.ts @@ -4,97 +4,44 @@ import { pluginReact } from '@rsbuild/plugin-react'; import { defineConfig } from '@rstest/core'; export default defineConfig({ globalSetup: ['./scripts/rstestGlobalSetup.ts'], - testTimeout: 15000, - projects: [ - { - name: 'main-app-node', - testEnvironment: 'node', - plugins: [pluginReact()], - federation: true, - exclude: ['test/**/*.rtl.*'], - dev: { writeToDisk: true }, - output: { module: false }, - tools: { - rspack: (config) => { - config.output = { ...(config.output ?? {}), publicPath: 'auto' }; - (config as any).builtins ??= {} as any; - (config as any).builtins.define = { - ...(((config as any).builtins.define as any) ?? {}), - __NODE_LOCAL_REMOTE__: 'true', - } as any; - config.plugins ??= []; - const nodeLocalEntryAbs = path.resolve( - __dirname, - '../node-local-remote/dist-node/remoteEntry.js', - ); - config.plugins.push( - new ModuleFederationPlugin({ - name: 'main_app_node', - library: { type: 'commonjs-module', name: 'main_app_node' }, - remoteType: 'script', - remotes: { - 'component-app': - 'component_app@http://localhost:3003/remoteEntry.js', - 'node-local-remote': `commonjs ${nodeLocalEntryAbs}`, - }, - runtimePlugins: ['@module-federation/node/runtimePlugin'], - shared: { - react: { - singleton: true, - eager: true, - requiredVersion: '19.2.3', - }, - 'react-dom': { - singleton: true, - eager: true, - requiredVersion: '19.2.3', - }, - }, - }), - ); - return config; - }, - }, + setupFiles: ['./scripts/rstest.rtl.setup.ts'], + testTimeout: 30_000, + testEnvironment: 'jsdom', + plugins: [pluginReact()], + federation: true, + tools: { + rspack: (config) => { + // Build host for Node federation runtime (async-node) even though tests run + // under JSDOM. This keeps remote resolution consistent with "node" tests. + config.target = 'async-node'; + config.optimization ??= {}; + config.optimization.splitChunks = false; + config.output = { ...(config.output ?? {}), publicPath: 'auto' }; + config.plugins ??= []; + config.plugins.push( + new ModuleFederationPlugin({ + name: 'main_app_web', + remoteType: 'script', + remotes: { + 'component-app': + 'component_app@http://localhost:3003/remoteEntry.js', + 'node-local-remote': `commonjs ${path.resolve( + __dirname, + '../node-local-remote/dist-node/remoteEntry.js', + )}`, + }, + runtimePlugins: ['@module-federation/node/runtimePlugin'], + shared: { + react: { singleton: true, eager: true, requiredVersion: '19.2.3' }, + 'react-dom': { + singleton: true, + eager: true, + requiredVersion: '19.2.3', + }, + }, + }), + ); + return config; }, - { - name: 'main-app-jsdom', - testEnvironment: 'jsdom', - plugins: [pluginReact()], - federation: true, - tools: { - rspack: (config) => { - config.output = { ...(config.output ?? {}), publicPath: 'auto' }; - config.plugins ??= []; - config.plugins.push( - new ModuleFederationPlugin({ - name: 'main_app_web', - remoteType: 'script', - remotes: { - 'component-app': - 'component_app@http://localhost:3001/remoteEntry.js', - 'node-local-remote': `commonjs ${path.resolve( - __dirname, - '../node-local-remote/dist-node/remoteEntry.js', - )}`, - }, - shared: { - react: { - singleton: true, - eager: true, - requiredVersion: '19.2.3', - }, - 'react-dom': { - singleton: true, - eager: true, - requiredVersion: '19.2.3', - }, - }, - }), - ); - return config; - }, - }, - include: ['test/**/*.rtl.*'], - }, - ], + }, }); diff --git a/examples/federation/main-app/scripts/rstest.rtl.setup.ts b/examples/federation/main-app/scripts/rstest.rtl.setup.ts new file mode 100644 index 000000000..c72c82009 --- /dev/null +++ b/examples/federation/main-app/scripts/rstest.rtl.setup.ts @@ -0,0 +1,41 @@ +import { expect } from '@rstest/core'; + +// Try to use @testing-library/jest-dom if available; otherwise provide a small +// subset of matchers so this example can run without extra deps. +let matchers: any = null; +try { + // eslint-disable-next-line @typescript-eslint/no-var-requires + matchers = require('@testing-library/jest-dom/matchers'); +} catch { + // ignore +} + +if (matchers) { + expect.extend(matchers); +} else { + expect.extend({ + toBeInTheDocument(received: any) { + const pass = + Boolean(received) && received.ownerDocument?.contains?.(received); + return { + pass, + message: () => + pass + ? 'expected element not to be in the document' + : 'expected element to be in the document', + }; + }, + toHaveAttribute(received: any, name: string, expected?: string) { + const actual = received?.getAttribute?.(name); + const pass = + typeof expected === 'undefined' ? actual != null : actual === expected; + return { + pass, + message: () => + pass + ? `expected element not to have attribute ${name}` + : `expected attribute ${name} to be ${String(expected)}, got ${String(actual)}`, + }; + }, + }); +} diff --git a/examples/federation/main-app/scripts/rstest.setup.ts b/examples/federation/main-app/scripts/rstest.setup.ts index 59c17d55f..b21b1f704 100644 --- a/examples/federation/main-app/scripts/rstest.setup.ts +++ b/examples/federation/main-app/scripts/rstest.setup.ts @@ -91,7 +91,9 @@ const ensureNodeRemoteImpl = async () => { 500, )); - if (!need3003 && !need3001) return; + if (!need3003 && !need3001) { + return; + } // Try to become the owner (cross-worker). let fd: number | null = null; @@ -130,6 +132,7 @@ const ensureNodeRemoteImpl = async () => { globalThis.__RSTEST_MF_CHILDREN__.push( start('component-app(web)', componentAppDir, 'pnpm', ['serve']), ); + // Wait for endpoints await waitForUrl(remoteEntryUrl); await waitForUrl('http://localhost:3001/remoteEntry.js'); @@ -177,12 +180,14 @@ const start = (name: string, cwd: string, cmd: string, args: string[]) => { const run = async (cwd: string, cmd: string, args: string[]) => { const child = spawn(cmd, args, { cwd, stdio: 'inherit', env: workerEnv }); await new Promise((resolveRun, rejectRun) => { - child.once('exit', (code) => { - if (code === 0) resolveRun(); - else + child.once('exit', (code: number | null) => { + if (code === 0) { + resolveRun(); + } else { rejectRun( new Error(`${cmd} ${args.join(' ')} exited with code ${code}`), ); + } }); child.once('error', rejectRun); }); @@ -190,6 +195,7 @@ const run = async (cwd: string, cmd: string, args: string[]) => { export const cleanupNodeRemote = async () => { // Kill by port first (covers detached/extra processes). + await killPort(3001).catch(() => {}); await killPort(3003).catch(() => {}); try { @@ -208,6 +214,8 @@ export const cleanupNodeRemote = async () => { }; export const ensureNodeRemote = async () => { + console.log('[Federation Setup] Starting federation setup...'); + // Keep state across test files within the same worker process. globalThis.__RSTEST_MF_CHILDREN__ ??= []; globalThis.__RSTEST_MF_OWNER__ ??= false; diff --git a/examples/federation/main-app/test/App.rtl.test.jsx b/examples/federation/main-app/test/App.rtl.test.jsx index 1a1af72b6..8217feb2d 100644 --- a/examples/federation/main-app/test/App.rtl.test.jsx +++ b/examples/federation/main-app/test/App.rtl.test.jsx @@ -13,7 +13,9 @@ test('renders main-app with federated remotes', async () => { ), ).toBeInTheDocument(); - expect(screen.getByText(/Buttons:/i)).toBeInTheDocument(); + expect( + await screen.findByRole('button', { name: /primary Button/i }), + ).toBeInTheDocument(); expect(screen.getByText(/hover me please/i)).toBeInTheDocument(); diff --git a/examples/federation/main-app/test/AppSsr.test.ts b/examples/federation/main-app/test/AppSsr.test.ts deleted file mode 100644 index a63f63b32..000000000 --- a/examples/federation/main-app/test/AppSsr.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { expect, test } from '@rstest/core'; -import React from 'react'; -import { renderToString } from 'react-dom/server'; - -test('App SSR renders component-app and node-local sections', async () => { - const { default: App } = await import('../App.jsx'); - const html = renderToString(React.createElement(App)); - const normalized = html.replace(//g, ''); - expect(normalized).toContain('Buttons:'); - expect(normalized).toContain('Dialog:'); - expect(normalized).toContain('hover me please!'); - expect(normalized).toContain('primary Button'); - expect(normalized).toContain('warning Button'); -}); diff --git a/examples/federation/main-app/test/ComponentRemotes.dynamic.test.ts b/examples/federation/main-app/test/ComponentRemotes.dynamic.test.ts deleted file mode 100644 index 1715a3092..000000000 --- a/examples/federation/main-app/test/ComponentRemotes.dynamic.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { expect, test } from '@rstest/core'; -import React from 'react'; -import { renderToString } from 'react-dom/server'; - -test('dynamic import Button renders SSR', async () => { - const { default: Button } = await import('component-app/Button'); - const html = renderToString(React.createElement(Button, { type: 'primary' })); - const normalized = html.replace(//g, ''); - expect(normalized).toContain('primary Button'); -}); - -test('dynamic import Dialog renders SSR when visible', async () => { - const { default: Dialog } = await import('component-app/Dialog'); - const html = renderToString( - React.createElement(Dialog, { visible: true, switchVisible: () => {} }), - ); - expect(html).toContain('What is your name ?'); -}); - -test('dynamic import ToolTip renders SSR with content/message', async () => { - const { default: ToolTip } = await import('component-app/ToolTip'); - const html = renderToString( - React.createElement(ToolTip, { - content: 'hover me please', - message: 'Hello,world!', - }), - ); - expect(html).toContain('hover me please'); - expect(html).toContain('data-content="Hello,world!"'); -}); diff --git a/examples/federation/main-app/test/ComponentRemotes.dynamic.test.tsx b/examples/federation/main-app/test/ComponentRemotes.dynamic.test.tsx new file mode 100644 index 000000000..b46427262 --- /dev/null +++ b/examples/federation/main-app/test/ComponentRemotes.dynamic.test.tsx @@ -0,0 +1,24 @@ +import { expect, test } from '@rstest/core'; +import { render, screen } from '@testing-library/react'; + +test('dynamic import Button renders', async () => { + const { default: Button } = await import('component-app/Button'); + render(