create-interview-cockpit 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -216,10 +216,12 @@ This lab uses real webpack 5 + webpack-dev-server + Module Federation.
216
216
 
217
217
  ## What is here
218
218
 
219
- - package.json runs three apps together: a host plus two remotes
219
+ - the root package.json orchestrates three npm workspaces: a host plus two remotes
220
+ - each app owns its own dependencies in its local package.json
220
221
  - apps/host consumes federated modules from the remotes
221
222
  - apps/profile exposes a profile widget
222
223
  - apps/checkout exposes a checkout widget
224
+ - react-router-dom is declared in each app package.json so routing experiments work across apps
223
225
 
224
226
  ## Good experiments
225
227
 
@@ -231,33 +233,29 @@ This lab uses real webpack 5 + webpack-dev-server + Module Federation.
231
233
  ## Notes
232
234
 
233
235
  - Ports are injected by the lab runner through environment variables.
234
- - If you change package.json, restart the webpack lab so dependencies/scripts are re-read.
236
+ - Each webpack config builds its shared dependency list from that app's runtime dependencies.
237
+ - If you add or remove dependencies in an app package.json, restart the webpack lab so npm workspaces reinstall them.
235
238
  `,
236
239
  "package.json": `{
237
240
  "name": "webpack-module-federation-lab",
238
241
  "private": true,
242
+ "workspaces": [
243
+ "apps/host",
244
+ "apps/profile",
245
+ "apps/checkout"
246
+ ],
239
247
  "scripts": {
240
- "dev": "concurrently -k -n host,profile,checkout -c cyan,magenta,yellow 'npm --prefix apps/host run dev' 'npm --prefix apps/profile run dev' 'npm --prefix apps/checkout run dev'",
241
- "dev:host": "npm --prefix apps/host run dev",
242
- "dev:profile": "npm --prefix apps/profile run dev",
243
- "dev:checkout": "npm --prefix apps/checkout run dev",
244
- "build": "npm --prefix apps/host run build && npm --prefix apps/profile run build && npm --prefix apps/checkout run build",
245
- "build:host": "npm --prefix apps/host run build",
246
- "build:profile": "npm --prefix apps/profile run build",
247
- "build:checkout": "npm --prefix apps/checkout run build"
248
- },
249
- "dependencies": {
250
- "react": "^19.0.0",
251
- "react-dom": "^19.0.0"
248
+ "dev": "concurrently -k -n host,profile,checkout -c cyan,magenta,yellow 'npm run dev --workspace=@mf-lab/host' 'npm run dev --workspace=@mf-lab/profile' 'npm run dev --workspace=@mf-lab/checkout'",
249
+ "dev:host": "npm run dev --workspace=@mf-lab/host",
250
+ "dev:profile": "npm run dev --workspace=@mf-lab/profile",
251
+ "dev:checkout": "npm run dev --workspace=@mf-lab/checkout",
252
+ "build": "npm run build --workspace=@mf-lab/host && npm run build --workspace=@mf-lab/profile && npm run build --workspace=@mf-lab/checkout",
253
+ "build:host": "npm run build --workspace=@mf-lab/host",
254
+ "build:profile": "npm run build --workspace=@mf-lab/profile",
255
+ "build:checkout": "npm run build --workspace=@mf-lab/checkout"
252
256
  },
253
257
  "devDependencies": {
254
- "concurrently": "^9.2.1",
255
- "esbuild": "^0.28.0",
256
- "esbuild-loader": "^4.4.3",
257
- "html-webpack-plugin": "^5.6.7",
258
- "webpack": "^5.106.2",
259
- "webpack-cli": "^7.0.2",
260
- "webpack-dev-server": "^5.2.3"
258
+ "concurrently": "^9.2.1"
261
259
  }
262
260
  }
263
261
  `,
@@ -279,14 +277,288 @@ This lab uses real webpack 5 + webpack-dev-server + Module Federation.
279
277
  "scripts": {
280
278
  "dev": "webpack serve --config webpack.config.js",
281
279
  "build": "webpack --config webpack.config.js"
280
+ },
281
+ "dependencies": {
282
+ "react": "^19.0.0",
283
+ "react-dom": "^19.0.0",
284
+ "react-router-dom": "^7.6.1"
285
+ },
286
+ "devDependencies": {
287
+ "esbuild": "^0.28.0",
288
+ "esbuild-loader": "^4.4.3",
289
+ "html-webpack-plugin": "^5.6.7",
290
+ "webpack": "^5.106.2",
291
+ "webpack-cli": "^7.0.2",
292
+ "webpack-dev-server": "^5.2.3"
293
+ }
294
+ }
295
+ `,
296
+ "apps/shared/mfInspector.js": `import React from "react";
297
+ import ReactDOM from "react-dom";
298
+ // NOTE: default import (not namespace import) is intentional — namespace objects
299
+ // are never reference-equal across MF consumers even when the singleton is shared,
300
+ // so comparing the default export is the only way to prove same-instance.
301
+
302
+ const app =
303
+ typeof __MF_INSPECTOR_APP__ === "string" ? __MF_INSPECTOR_APP__ : "unknown";
304
+ const sandboxId =
305
+ typeof __MF_INSPECTOR_SANDBOX_ID__ === "string"
306
+ ? __MF_INSPECTOR_SANDBOX_ID__
307
+ : "";
308
+ const declaredConfig =
309
+ typeof __MF_INSPECTOR_DECLARED_CONFIG__ !== "undefined"
310
+ ? __MF_INSPECTOR_DECLARED_CONFIG__
311
+ : null;
312
+ const runtimeId =
313
+ typeof crypto !== "undefined" && typeof crypto.randomUUID === "function"
314
+ ? crypto.randomUUID()
315
+ : app + "-" + Date.now() + "-" + Math.random().toString(36).slice(2);
316
+
317
+ let attachedRouteListeners = false;
318
+
319
+ function getRoute() {
320
+ if (typeof window === "undefined" || !window.location) return "/";
321
+ const route =
322
+ window.location.pathname +
323
+ window.location.search +
324
+ window.location.hash;
325
+ return route || "/";
326
+ }
327
+
328
+ function cloneJsonSafe(value) {
329
+ if (value == null) return value;
330
+ try {
331
+ return JSON.parse(JSON.stringify(value));
332
+ } catch {
333
+ return value;
334
+ }
335
+ }
336
+
337
+ export async function ensureShareScopeReady() {
338
+ try {
339
+ if (typeof __webpack_init_sharing__ === "function") {
340
+ await __webpack_init_sharing__("default");
341
+ }
342
+ } catch (error) {
343
+ emitInspectorEvent("share-init-error", {
344
+ message: error instanceof Error ? error.message : String(error),
345
+ });
282
346
  }
283
347
  }
348
+
349
+ export function snapshotShareScopes() {
350
+ try {
351
+ if (typeof __webpack_share_scopes__ === "undefined") return {};
352
+ return Object.fromEntries(
353
+ Object.entries(__webpack_share_scopes__).map(([scopeName, scopeValue]) => [
354
+ scopeName,
355
+ Object.fromEntries(
356
+ Object.entries(scopeValue || {}).map(([packageName, versions]) => [
357
+ packageName,
358
+ Object.entries(versions || {}).map(([version, entry]) => ({
359
+ version,
360
+ from: entry && typeof entry.from === "string" ? entry.from : null,
361
+ eager: Boolean(entry && entry.eager),
362
+ loaded: Boolean(entry && entry.loaded),
363
+ hasGet: Boolean(entry && typeof entry.get === "function"),
364
+ })),
365
+ ]),
366
+ ),
367
+ ]),
368
+ );
369
+ } catch (error) {
370
+ return {
371
+ __error: error instanceof Error ? error.message : String(error),
372
+ };
373
+ }
374
+ }
375
+
376
+ export function emitInspectorEvent(kind, payload) {
377
+ if (!sandboxId || typeof window === "undefined" || !window.parent) return;
378
+ window.parent.postMessage(
379
+ {
380
+ type: "mf-inspector-event",
381
+ sandboxId,
382
+ app,
383
+ runtimeId,
384
+ kind,
385
+ route: getRoute(),
386
+ timestamp: Date.now(),
387
+ payload: cloneJsonSafe(payload),
388
+ },
389
+ "*",
390
+ );
391
+ }
392
+
393
+ function attachRouteListeners() {
394
+ if (attachedRouteListeners || typeof window === "undefined") return;
395
+ attachedRouteListeners = true;
396
+ window.addEventListener("popstate", () => {
397
+ void emitRouteSnapshot("popstate");
398
+ });
399
+ window.addEventListener("hashchange", () => {
400
+ void emitRouteSnapshot("hashchange");
401
+ });
402
+ }
403
+
404
+ export function emitDeclaredConfig() {
405
+ emitInspectorEvent("declared-config", {
406
+ declaredConfig: cloneJsonSafe(declaredConfig),
407
+ });
408
+ }
409
+
410
+ export async function emitRuntimeBoot(label) {
411
+ attachRouteListeners();
412
+ await ensureShareScopeReady();
413
+ emitDeclaredConfig();
414
+ emitInspectorEvent("runtime-boot", {
415
+ label: label || "boot",
416
+ reactVersion: React.version || null,
417
+ reactDomVersion: ReactDOM.version || null,
418
+ declaredConfig: cloneJsonSafe(declaredConfig),
419
+ });
420
+ emitInspectorEvent("share-snapshot", {
421
+ label: (label || "boot") + ":share-snapshot",
422
+ shareScopes: snapshotShareScopes(),
423
+ });
424
+ }
425
+
426
+ export async function emitRouteSnapshot(label) {
427
+ await ensureShareScopeReady();
428
+ emitInspectorEvent("route-change", {
429
+ label: label || "route",
430
+ shareScopes: snapshotShareScopes(),
431
+ });
432
+ }
433
+
434
+ export function getRemoteInspectorBridge() {
435
+ return {
436
+ app,
437
+ reactVersion: React.version || null,
438
+ reactDomVersion: ReactDOM.version || null,
439
+ reactObject: React,
440
+ reactDomObject: ReactDOM,
441
+ declaredConfig: cloneJsonSafe(declaredConfig),
442
+ shareScopes: snapshotShareScopes(),
443
+ };
444
+ }
445
+
446
+ export function makeInspectableLazy(remoteKey, componentLoad, debugLoad) {
447
+ return async () => {
448
+ await ensureShareScopeReady();
449
+ emitInspectorEvent("remote-load-start", {
450
+ remoteKey,
451
+ shareScopes: snapshotShareScopes(),
452
+ });
453
+ const startedAt =
454
+ typeof performance !== "undefined" && typeof performance.now === "function"
455
+ ? performance.now()
456
+ : Date.now();
457
+
458
+ try {
459
+ const componentModule = await componentLoad();
460
+ const finishedAt =
461
+ typeof performance !== "undefined" && typeof performance.now === "function"
462
+ ? performance.now()
463
+ : Date.now();
464
+
465
+ emitInspectorEvent("remote-load-success", {
466
+ remoteKey,
467
+ durationMs: Number((finishedAt - startedAt).toFixed(2)),
468
+ exportKeys: Object.keys(componentModule || {}),
469
+ shareScopes: snapshotShareScopes(),
470
+ });
471
+
472
+ if (debugLoad) {
473
+ try {
474
+ const debugModule = await debugLoad();
475
+ const bridgeValue =
476
+ typeof debugModule.getRemoteInspectorBridge === "function"
477
+ ? debugModule.getRemoteInspectorBridge()
478
+ : typeof debugModule.default === "function"
479
+ ? debugModule.default()
480
+ : debugModule.default || debugModule;
481
+
482
+ if (bridgeValue) {
483
+ emitInspectorEvent("identity-check", {
484
+ remoteKey,
485
+ remoteApp:
486
+ typeof bridgeValue.app === "string"
487
+ ? bridgeValue.app
488
+ : remoteKey.split("/")[0],
489
+ reactVersion: bridgeValue.reactVersion || null,
490
+ reactDomVersion: bridgeValue.reactDomVersion || null,
491
+ sameReactInstance: bridgeValue.reactObject === React,
492
+ sameReactDomInstance: bridgeValue.reactDomObject === ReactDOM,
493
+ declaredConfig: cloneJsonSafe(bridgeValue.declaredConfig),
494
+ shareScopes: cloneJsonSafe(bridgeValue.shareScopes),
495
+ });
496
+ }
497
+ } catch (error) {
498
+ emitInspectorEvent("identity-check-error", {
499
+ remoteKey,
500
+ message: error instanceof Error ? error.message : String(error),
501
+ shareScopes: snapshotShareScopes(),
502
+ });
503
+ }
504
+ }
505
+
506
+ return componentModule;
507
+ } catch (error) {
508
+ emitInspectorEvent("remote-load-error", {
509
+ remoteKey,
510
+ message: error instanceof Error ? error.message : String(error),
511
+ shareScopes: snapshotShareScopes(),
512
+ });
513
+ throw error;
514
+ }
515
+ };
516
+ }
517
+ `,
518
+ "apps/shared/buildSharedConfig.js": `function createSharedConfig(packageJson) {
519
+ const dependencyVersions =
520
+ packageJson && typeof packageJson === "object"
521
+ ? packageJson.dependencies || {}
522
+ : {};
523
+
524
+ const sharedOverrides = {
525
+ react: {
526
+ singleton: true,
527
+ requiredVersion: dependencyVersions.react || false,
528
+ },
529
+ "react-dom": {
530
+ singleton: true,
531
+ requiredVersion: dependencyVersions["react-dom"] || false,
532
+ },
533
+ "react-router-dom": {
534
+ singleton: true,
535
+ requiredVersion: dependencyVersions["react-router-dom"] || false,
536
+ },
537
+ };
538
+
539
+ // Add package names here if you want them installed but NOT shared.
540
+ const unsharedPackages = new Set([]);
541
+
542
+ return Object.fromEntries(
543
+ Object.keys(dependencyVersions)
544
+ .filter((packageName) => !unsharedPackages.has(packageName))
545
+ .map((packageName) => [
546
+ packageName,
547
+ sharedOverrides[packageName] ?? {
548
+ requiredVersion: dependencyVersions[packageName] || false,
549
+ },
550
+ ]),
551
+ );
552
+ }
553
+
554
+ module.exports = { createSharedConfig };
284
555
  `,
285
556
  "apps/host/src/index.jsx": `import("./bootstrap");
286
557
  `,
287
558
  "apps/host/src/bootstrap.jsx": `import React from "react";
288
559
  import { createRoot } from "react-dom/client";
289
560
  import App from "./App";
561
+ import { emitRuntimeBoot } from "../../shared/mfInspector";
290
562
 
291
563
  const root = createRoot(document.getElementById("root"));
292
564
 
@@ -295,11 +567,26 @@ root.render(
295
567
  <App />
296
568
  </React.StrictMode>,
297
569
  );
570
+
571
+ void emitRuntimeBoot("host-bootstrap");
298
572
  `,
299
573
  "apps/host/src/App.jsx": `import React, { Suspense } from "react";
300
-
301
- const ProfileCard = React.lazy(() => import("profile/ProfileCard"));
302
- const CheckoutPanel = React.lazy(() => import("checkout/CheckoutPanel"));
574
+ import { makeInspectableLazy } from "../../shared/mfInspector";
575
+
576
+ const ProfileCard = React.lazy(
577
+ makeInspectableLazy(
578
+ "profile/ProfileCard",
579
+ () => import("profile/ProfileCard"),
580
+ () => import("profile/InspectorBridge"),
581
+ ),
582
+ );
583
+ const CheckoutPanel = React.lazy(
584
+ makeInspectableLazy(
585
+ "checkout/CheckoutPanel",
586
+ () => import("checkout/CheckoutPanel"),
587
+ () => import("checkout/InspectorBridge"),
588
+ ),
589
+ );
303
590
 
304
591
  function RemoteBoundary({ title, children }) {
305
592
  return (
@@ -366,12 +653,25 @@ export default function App() {
366
653
  }
367
654
  `,
368
655
  "apps/host/webpack.config.js": `const path = require("path");
656
+ const webpack = require("webpack");
369
657
  const HtmlWebpackPlugin = require("html-webpack-plugin");
370
- const { ModuleFederationPlugin } = require("webpack").container;
658
+ const { ModuleFederationPlugin } = webpack.container;
659
+ const packageJson = require("./package.json");
660
+ const { createSharedConfig } = require("../shared/buildSharedConfig");
371
661
 
372
662
  const hostPort = Number(process.env.HOST_PORT || 3100);
373
663
  const profilePort = Number(process.env.PROFILE_PORT || 3101);
374
664
  const checkoutPort = Number(process.env.CHECKOUT_PORT || 3102);
665
+ const sharedConfig = createSharedConfig(packageJson);
666
+ const remoteConfig = {
667
+ profile: "profile@http://localhost:" + profilePort + "/remoteEntry.js",
668
+ checkout: "checkout@http://localhost:" + checkoutPort + "/remoteEntry.js",
669
+ };
670
+ const inspectorConfig = {
671
+ app: "host",
672
+ remotes: remoteConfig,
673
+ shared: sharedConfig,
674
+ };
375
675
 
376
676
  module.exports = {
377
677
  mode: "development",
@@ -409,16 +709,15 @@ module.exports = {
409
709
  },
410
710
  },
411
711
  plugins: [
712
+ new webpack.DefinePlugin({
713
+ __MF_INSPECTOR_APP__: JSON.stringify("host"),
714
+ __MF_INSPECTOR_SANDBOX_ID__: JSON.stringify(process.env.MF_SANDBOX_ID || ""),
715
+ __MF_INSPECTOR_DECLARED_CONFIG__: JSON.stringify(inspectorConfig),
716
+ }),
412
717
  new ModuleFederationPlugin({
413
718
  name: "host",
414
- remotes: {
415
- profile: "profile@http://localhost:" + profilePort + "/remoteEntry.js",
416
- checkout: "checkout@http://localhost:" + checkoutPort + "/remoteEntry.js",
417
- },
418
- shared: {
419
- react: { singleton: true, requiredVersion: false },
420
- "react-dom": { singleton: true, requiredVersion: false },
421
- },
719
+ remotes: remoteConfig,
720
+ shared: sharedConfig,
422
721
  }),
423
722
  new HtmlWebpackPlugin({
424
723
  template: path.resolve(__dirname, "./public/index.html"),
@@ -444,14 +743,33 @@ module.exports = {
444
743
  "scripts": {
445
744
  "dev": "webpack serve --config webpack.config.js",
446
745
  "build": "webpack --config webpack.config.js"
746
+ },
747
+ "dependencies": {
748
+ "react": "^19.0.0",
749
+ "react-dom": "^19.0.0",
750
+ "react-router-dom": "^7.6.1"
751
+ },
752
+ "devDependencies": {
753
+ "esbuild": "^0.28.0",
754
+ "esbuild-loader": "^4.4.3",
755
+ "html-webpack-plugin": "^5.6.7",
756
+ "webpack": "^5.106.2",
757
+ "webpack-cli": "^7.0.2",
758
+ "webpack-dev-server": "^5.2.3"
447
759
  }
448
760
  }
761
+ `,
762
+ "apps/profile/src/inspectorBridge.js": `import { getRemoteInspectorBridge } from "../../shared/mfInspector";
763
+
764
+ export { getRemoteInspectorBridge };
765
+ export default getRemoteInspectorBridge;
449
766
  `,
450
767
  "apps/profile/src/index.jsx": `import("./bootstrap");
451
768
  `,
452
769
  "apps/profile/src/bootstrap.jsx": `import React from "react";
453
770
  import { createRoot } from "react-dom/client";
454
771
  import App from "./App";
772
+ import { emitRuntimeBoot } from "../../shared/mfInspector";
455
773
 
456
774
  const root = createRoot(document.getElementById("root"));
457
775
 
@@ -460,6 +778,8 @@ root.render(
460
778
  <App />
461
779
  </React.StrictMode>,
462
780
  );
781
+
782
+ void emitRuntimeBoot("profile-bootstrap");
463
783
  `,
464
784
  "apps/profile/src/App.jsx": `import React from "react";
465
785
  import ProfileCard from "./ProfileCard";
@@ -496,10 +816,23 @@ export default function ProfileCard() {
496
816
  }
497
817
  `,
498
818
  "apps/profile/webpack.config.js": `const path = require("path");
819
+ const webpack = require("webpack");
499
820
  const HtmlWebpackPlugin = require("html-webpack-plugin");
500
- const { ModuleFederationPlugin } = require("webpack").container;
821
+ const { ModuleFederationPlugin } = webpack.container;
822
+ const packageJson = require("./package.json");
823
+ const { createSharedConfig } = require("../shared/buildSharedConfig");
501
824
 
502
825
  const profilePort = Number(process.env.PROFILE_PORT || 3101);
826
+ const sharedConfig = createSharedConfig(packageJson);
827
+ const exposeConfig = {
828
+ "./ProfileCard": path.resolve(__dirname, "./src/ProfileCard.jsx"),
829
+ "./InspectorBridge": path.resolve(__dirname, "./src/inspectorBridge.js"),
830
+ };
831
+ const inspectorConfig = {
832
+ app: "profile",
833
+ exposes: Object.keys(exposeConfig),
834
+ shared: sharedConfig,
835
+ };
503
836
 
504
837
  module.exports = {
505
838
  mode: "development",
@@ -530,22 +863,23 @@ module.exports = {
530
863
  },
531
864
  devServer: {
532
865
  port: profilePort,
866
+ historyApiFallback: true,
533
867
  hot: true,
534
868
  headers: {
535
869
  "Access-Control-Allow-Origin": "*",
536
870
  },
537
871
  },
538
872
  plugins: [
873
+ new webpack.DefinePlugin({
874
+ __MF_INSPECTOR_APP__: JSON.stringify("profile"),
875
+ __MF_INSPECTOR_SANDBOX_ID__: JSON.stringify(process.env.MF_SANDBOX_ID || ""),
876
+ __MF_INSPECTOR_DECLARED_CONFIG__: JSON.stringify(inspectorConfig),
877
+ }),
539
878
  new ModuleFederationPlugin({
540
879
  name: "profile",
541
880
  filename: "remoteEntry.js",
542
- exposes: {
543
- "./ProfileCard": path.resolve(__dirname, "./src/ProfileCard.jsx"),
544
- },
545
- shared: {
546
- react: { singleton: true, requiredVersion: false },
547
- "react-dom": { singleton: true, requiredVersion: false },
548
- },
881
+ exposes: exposeConfig,
882
+ shared: sharedConfig,
549
883
  }),
550
884
  new HtmlWebpackPlugin({
551
885
  template: path.resolve(__dirname, "./public/index.html"),
@@ -571,14 +905,33 @@ module.exports = {
571
905
  "scripts": {
572
906
  "dev": "webpack serve --config webpack.config.js",
573
907
  "build": "webpack --config webpack.config.js"
908
+ },
909
+ "dependencies": {
910
+ "react": "^19.0.0",
911
+ "react-dom": "^19.0.0",
912
+ "react-router-dom": "^7.6.1"
913
+ },
914
+ "devDependencies": {
915
+ "esbuild": "^0.28.0",
916
+ "esbuild-loader": "^4.4.3",
917
+ "html-webpack-plugin": "^5.6.7",
918
+ "webpack": "^5.106.2",
919
+ "webpack-cli": "^7.0.2",
920
+ "webpack-dev-server": "^5.2.3"
574
921
  }
575
922
  }
923
+ `,
924
+ "apps/checkout/src/inspectorBridge.js": `import { getRemoteInspectorBridge } from "../../shared/mfInspector";
925
+
926
+ export { getRemoteInspectorBridge };
927
+ export default getRemoteInspectorBridge;
576
928
  `,
577
929
  "apps/checkout/src/index.jsx": `import("./bootstrap");
578
930
  `,
579
931
  "apps/checkout/src/bootstrap.jsx": `import React from "react";
580
932
  import { createRoot } from "react-dom/client";
581
933
  import App from "./App";
934
+ import { emitRuntimeBoot } from "../../shared/mfInspector";
582
935
 
583
936
  const root = createRoot(document.getElementById("root"));
584
937
 
@@ -587,6 +940,8 @@ root.render(
587
940
  <App />
588
941
  </React.StrictMode>,
589
942
  );
943
+
944
+ void emitRuntimeBoot("checkout-bootstrap");
590
945
  `,
591
946
  "apps/checkout/src/App.jsx": `import React from "react";
592
947
  import CheckoutPanel from "./CheckoutPanel";
@@ -631,10 +986,23 @@ export default function CheckoutPanel() {
631
986
  }
632
987
  `,
633
988
  "apps/checkout/webpack.config.js": `const path = require("path");
989
+ const webpack = require("webpack");
634
990
  const HtmlWebpackPlugin = require("html-webpack-plugin");
635
- const { ModuleFederationPlugin } = require("webpack").container;
991
+ const { ModuleFederationPlugin } = webpack.container;
992
+ const packageJson = require("./package.json");
993
+ const { createSharedConfig } = require("../shared/buildSharedConfig");
636
994
 
637
995
  const checkoutPort = Number(process.env.CHECKOUT_PORT || 3102);
996
+ const sharedConfig = createSharedConfig(packageJson);
997
+ const exposeConfig = {
998
+ "./CheckoutPanel": path.resolve(__dirname, "./src/CheckoutPanel.jsx"),
999
+ "./InspectorBridge": path.resolve(__dirname, "./src/inspectorBridge.js"),
1000
+ };
1001
+ const inspectorConfig = {
1002
+ app: "checkout",
1003
+ exposes: Object.keys(exposeConfig),
1004
+ shared: sharedConfig,
1005
+ };
638
1006
 
639
1007
  module.exports = {
640
1008
  mode: "development",
@@ -665,22 +1033,23 @@ module.exports = {
665
1033
  },
666
1034
  devServer: {
667
1035
  port: checkoutPort,
1036
+ historyApiFallback: true,
668
1037
  hot: true,
669
1038
  headers: {
670
1039
  "Access-Control-Allow-Origin": "*",
671
1040
  },
672
1041
  },
673
1042
  plugins: [
1043
+ new webpack.DefinePlugin({
1044
+ __MF_INSPECTOR_APP__: JSON.stringify("checkout"),
1045
+ __MF_INSPECTOR_SANDBOX_ID__: JSON.stringify(process.env.MF_SANDBOX_ID || ""),
1046
+ __MF_INSPECTOR_DECLARED_CONFIG__: JSON.stringify(inspectorConfig),
1047
+ }),
674
1048
  new ModuleFederationPlugin({
675
1049
  name: "checkout",
676
1050
  filename: "remoteEntry.js",
677
- exposes: {
678
- "./CheckoutPanel": path.resolve(__dirname, "./src/CheckoutPanel.jsx"),
679
- },
680
- shared: {
681
- react: { singleton: true, requiredVersion: false },
682
- "react-dom": { singleton: true, requiredVersion: false },
683
- },
1051
+ exposes: exposeConfig,
1052
+ shared: sharedConfig,
684
1053
  }),
685
1054
  new HtmlWebpackPlugin({
686
1055
  template: path.resolve(__dirname, "./public/index.html"),
@@ -1,30 +1 @@
1
- {
2
- "root": [
3
- "./src/app.tsx",
4
- "./src/api.ts",
5
- "./src/main.tsx",
6
- "./src/store.ts",
7
- "./src/types.ts",
8
- "./src/vite-env.d.ts",
9
- "./src/components/aisettingsmodal.tsx",
10
- "./src/components/annotationdialog.tsx",
11
- "./src/components/chatmessage.tsx",
12
- "./src/components/chatview.tsx",
13
- "./src/components/codecontextpanel.tsx",
14
- "./src/components/codelineannotationpopup.tsx",
15
- "./src/components/coderunnermodal.tsx",
16
- "./src/components/docrefmodal.tsx",
17
- "./src/components/fileattachments.tsx",
18
- "./src/components/filepickermodal.tsx",
19
- "./src/components/fileviewermodal.tsx",
20
- "./src/components/linkedconvospicker.tsx",
21
- "./src/components/markdownrenderer.tsx",
22
- "./src/components/mermaiddiagram.tsx",
23
- "./src/components/plotembed.tsx",
24
- "./src/components/sidebar.tsx",
25
- "./src/components/textannotator.tsx",
26
- "./src/components/vizcraftembed.tsx",
27
- "./src/components/workspaceswitcher.tsx"
28
- ],
29
- "version": "5.9.3"
30
- }
1
+ {"root":["./src/app.tsx","./src/api.ts","./src/infralab.ts","./src/main.tsx","./src/reactlab.ts","./src/store.ts","./src/types.ts","./src/vite-env.d.ts","./src/components/aisettingsmodal.tsx","./src/components/annotationdialog.tsx","./src/components/chatmessage.tsx","./src/components/chatview.tsx","./src/components/codecontextpanel.tsx","./src/components/codelineannotationpopup.tsx","./src/components/coderunnermodal.tsx","./src/components/docrefmodal.tsx","./src/components/fileattachments.tsx","./src/components/filepickermodal.tsx","./src/components/fileviewermodal.tsx","./src/components/infralabmodal.tsx","./src/components/linkedconvospicker.tsx","./src/components/markdownrenderer.tsx","./src/components/mermaiddiagram.tsx","./src/components/notesmodal.tsx","./src/components/plotembed.tsx","./src/components/sidebar.tsx","./src/components/textannotator.tsx","./src/components/vizcraftembed.tsx","./src/components/workspaceswitcher.tsx"],"errors":true,"version":"5.9.3"}
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "0.7.0"
2
+ "version": "0.9.0"
3
3
  }