@bleedingdev/modern-js-create 3.2.0-ultramodern.37 → 3.2.0-ultramodern.39

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.
package/dist/index.js CHANGED
@@ -2712,10 +2712,8 @@ function createShellPage() {
2712
2712
  return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2713
2713
  import { Helmet } from '@modern-js/runtime/head';
2714
2714
  import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2715
- import Header from 'explore/Header';
2716
- import StorePicker from 'explore/StorePicker';
2717
- import MiniCart from 'checkout/MiniCart';
2718
2715
  import { ultramodernLocalisedUrls } from '../ultramodern-route-metadata';
2716
+ import { Header, MiniCart, StorePicker } from '../remote-components';
2719
2717
  import { ultramodernUiMarker } from '../../ultramodern-build';
2720
2718
 
2721
2719
  const languageCodes = ['en', 'cs'] as const;
@@ -2723,7 +2721,7 @@ const languageCodes = ['en', 'cs'] as const;
2723
2721
  ${createLocalizedHeadComponent()}
2724
2722
  export default function ShellHome() {
2725
2723
  const { i18nInstance, language } = useModernI18n();
2726
- const t = i18nInstance.t.bind(i18nInstance);
2724
+ const t = i18nInstance['t'].bind(i18nInstance);
2727
2725
  const location = useLocation();
2728
2726
  const suffix = locationSuffix(location);
2729
2727
 
@@ -2773,17 +2771,15 @@ function createShellTractorsPage() {
2773
2771
  return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2774
2772
  import { Helmet } from '@modern-js/runtime/head';
2775
2773
  import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2776
- import Header from 'explore/Header';
2777
- import Recommendations from 'explore/Recommendations';
2778
- import MiniCart from 'checkout/MiniCart';
2779
2774
  import { ultramodernLocalisedUrls } from '../../ultramodern-route-metadata';
2775
+ import { Header, MiniCart, Recommendations } from '../../remote-components';
2780
2776
 
2781
2777
  const languageCodes = ['en', 'cs'] as const;
2782
2778
 
2783
2779
  ${createLocalizedHeadComponent()}
2784
2780
  export default function ShellTractorsPage() {
2785
2781
  const { i18nInstance, language } = useModernI18n();
2786
- const t = i18nInstance.t.bind(i18nInstance);
2782
+ const t = i18nInstance['t'].bind(i18nInstance);
2787
2783
  const location = useLocation();
2788
2784
  const suffix = locationSuffix(location);
2789
2785
 
@@ -2816,17 +2812,15 @@ function createShellProductPage() {
2816
2812
  return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2817
2813
  import { Helmet } from '@modern-js/runtime/head';
2818
2814
  import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2819
- import Header from 'explore/Header';
2820
- import ProductPage from 'decide/ProductPage';
2821
- import MiniCart from 'checkout/MiniCart';
2822
2815
  import { ultramodernLocalisedUrls } from '../../../ultramodern-route-metadata';
2816
+ import { Header, MiniCart, ProductPage } from '../../../remote-components';
2823
2817
 
2824
2818
  const languageCodes = ['en', 'cs'] as const;
2825
2819
 
2826
2820
  ${createLocalizedHeadComponent()}
2827
2821
  export default function ShellProductPage() {
2828
2822
  const { i18nInstance, language } = useModernI18n();
2829
- const t = i18nInstance.t.bind(i18nInstance);
2823
+ const t = i18nInstance['t'].bind(i18nInstance);
2830
2824
  const location = useLocation();
2831
2825
  const suffix = locationSuffix(location);
2832
2826
 
@@ -2859,16 +2853,15 @@ function createShellCartPage() {
2859
2853
  return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2860
2854
  import { Helmet } from '@modern-js/runtime/head';
2861
2855
  import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2862
- import Header from 'explore/Header';
2863
- import CartPage from 'checkout/CartPage';
2864
2856
  import { ultramodernLocalisedUrls } from '../../ultramodern-route-metadata';
2857
+ import { CartPage, Header } from '../../remote-components';
2865
2858
 
2866
2859
  const languageCodes = ['en', 'cs'] as const;
2867
2860
 
2868
2861
  ${createLocalizedHeadComponent()}
2869
2862
  export default function ShellCartPage() {
2870
2863
  const { i18nInstance, language } = useModernI18n();
2871
- const t = i18nInstance.t.bind(i18nInstance);
2864
+ const t = i18nInstance['t'].bind(i18nInstance);
2872
2865
  const location = useLocation();
2873
2866
  const suffix = locationSuffix(location);
2874
2867
 
@@ -2896,6 +2889,43 @@ export default function ShellCartPage() {
2896
2889
  }
2897
2890
  `;
2898
2891
  }
2892
+ function createShellRemoteComponents() {
2893
+ return `import { loadRemote } from '@module-federation/modern-js-v3/runtime';
2894
+ import * as React from 'react';
2895
+
2896
+ type RemoteComponent = React.ComponentType<Record<string, never>>;
2897
+
2898
+ const lazyRemote = (moduleId: string) => {
2899
+ const Component = React.lazy(async () => {
2900
+ const module = await loadRemote(moduleId);
2901
+ const remote = (module as { default?: unknown }).default;
2902
+
2903
+ if (typeof remote !== 'function') {
2904
+ throw new Error(\`Remote "\${moduleId}" did not expose a React component.\`);
2905
+ }
2906
+
2907
+ return {
2908
+ default: remote as RemoteComponent,
2909
+ };
2910
+ });
2911
+
2912
+ return function RemoteComponent() {
2913
+ return (
2914
+ <React.Suspense fallback={null}>
2915
+ <Component />
2916
+ </React.Suspense>
2917
+ );
2918
+ };
2919
+ };
2920
+
2921
+ export const Header = lazyRemote('explore/Header');
2922
+ export const StorePicker = lazyRemote('explore/StorePicker');
2923
+ export const Recommendations = lazyRemote('explore/Recommendations');
2924
+ export const ProductPage = lazyRemote('decide/ProductPage');
2925
+ export const MiniCart = lazyRemote('checkout/MiniCart');
2926
+ export const CartPage = lazyRemote('checkout/CartPage');
2927
+ `;
2928
+ }
2899
2929
  function createRemotePage(app) {
2900
2930
  const effectBffImport = appHasEffectApi(app) ? `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2901
2931
  import { Helmet } from '@modern-js/runtime/head';
@@ -2934,7 +2964,7 @@ import { ultramodernUiMarker } from '../../ultramodern-build';
2934
2964
  ${createLocalizedHeadComponent()}
2935
2965
  export default function ${toPascalCase(app.id)}Home() {
2936
2966
  const { i18nInstance, language } = useModernI18n();
2937
- const t = i18nInstance.t.bind(i18nInstance);
2967
+ const t = i18nInstance['t'].bind(i18nInstance);
2938
2968
  const location = useLocation();
2939
2969
  const suffix = locationSuffix(location);
2940
2970
  ${effectBffState} return (
@@ -3007,7 +3037,7 @@ function createRemoteExposeComponent(app, expose) {
3007
3037
 
3008
3038
  export default function Header() {
3009
3039
  const { i18nInstance, language } = useModernI18n();
3010
- const t = i18nInstance.t.bind(i18nInstance);
3040
+ const t = i18nInstance['t'].bind(i18nInstance);
3011
3041
 
3012
3042
  return (
3013
3043
  <header className="commerce-header" data-mf-boundary="explore">
@@ -3031,7 +3061,7 @@ const tractors = [
3031
3061
 
3032
3062
  export default function Recommendations() {
3033
3063
  const { i18nInstance, language } = useModernI18n();
3034
- const t = i18nInstance.t.bind(i18nInstance);
3064
+ const t = i18nInstance['t'].bind(i18nInstance);
3035
3065
 
3036
3066
  return (
3037
3067
  <section className="commerce-page" data-mf-boundary="explore">
@@ -3052,7 +3082,7 @@ export default function Recommendations() {
3052
3082
 
3053
3083
  export default function StorePicker() {
3054
3084
  const { i18nInstance } = useModernI18n();
3055
- const t = i18nInstance.t.bind(i18nInstance);
3085
+ const t = i18nInstance['t'].bind(i18nInstance);
3056
3086
 
3057
3087
  return (
3058
3088
  <section className="commerce-page" data-mf-boundary="explore">
@@ -3078,12 +3108,11 @@ export default function StorePicker() {
3078
3108
  if ('./Widget' === expose) return createRemoteWidget(app);
3079
3109
  const componentName = `${toPascalCase(app.domain ?? app.id)}${toPascalCase(expose.replace(/^\.\//u, ''))}`;
3080
3110
  if ('remote-decide' === app.id && './ProductPage' === expose) return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
3081
- import AddToCart from 'checkout/AddToCart';
3082
- import Recommendations from 'explore/Recommendations';
3111
+ import { AddToCart, Recommendations } from './remote-components';
3083
3112
 
3084
3113
  export default function ${componentName}() {
3085
3114
  const { i18nInstance } = useModernI18n();
3086
- const t = i18nInstance.t.bind(i18nInstance);
3115
+ const t = i18nInstance['t'].bind(i18nInstance);
3087
3116
 
3088
3117
  return (
3089
3118
  <>
@@ -3111,7 +3140,7 @@ import { useCartLines } from '../cart-store';
3111
3140
 
3112
3141
  export default function ${componentName}() {
3113
3142
  const { i18nInstance, language } = useModernI18n();
3114
- const t = i18nInstance.t.bind(i18nInstance);
3143
+ const t = i18nInstance['t'].bind(i18nInstance);
3115
3144
  const cart = useCartLines();
3116
3145
 
3117
3146
  return (
@@ -3131,7 +3160,7 @@ import { useCartLines } from '../cart-store';
3131
3160
 
3132
3161
  export default function ${componentName}() {
3133
3162
  const { i18nInstance, language } = useModernI18n();
3134
- const t = i18nInstance.t.bind(i18nInstance);
3163
+ const t = i18nInstance['t'].bind(i18nInstance);
3135
3164
  const cart = useCartLines();
3136
3165
  const count = cart.lines.reduce((sum, line) => sum + line.quantity, 0);
3137
3166
 
@@ -3147,7 +3176,7 @@ import { useCartLines } from '../cart-store';
3147
3176
 
3148
3177
  export default function ${componentName}() {
3149
3178
  const { i18nInstance } = useModernI18n();
3150
- const t = i18nInstance.t.bind(i18nInstance);
3179
+ const t = i18nInstance['t'].bind(i18nInstance);
3151
3180
  const cart = useCartLines();
3152
3181
 
3153
3182
  return (
@@ -3192,6 +3221,39 @@ export default function ${componentName}() {
3192
3221
  }
3193
3222
  `;
3194
3223
  }
3224
+ function createDecideRemoteComponents() {
3225
+ return `import { loadRemote } from '@module-federation/modern-js-v3/runtime';
3226
+ import * as React from 'react';
3227
+
3228
+ type RemoteComponent = React.ComponentType<Record<string, never>>;
3229
+
3230
+ const lazyRemote = (moduleId: string) => {
3231
+ const Component = React.lazy(async () => {
3232
+ const module = await loadRemote(moduleId);
3233
+ const remote = (module as { default?: unknown }).default;
3234
+
3235
+ if (typeof remote !== 'function') {
3236
+ throw new Error(\`Remote "\${moduleId}" did not expose a React component.\`);
3237
+ }
3238
+
3239
+ return {
3240
+ default: remote as RemoteComponent,
3241
+ };
3242
+ });
3243
+
3244
+ return function RemoteComponent() {
3245
+ return (
3246
+ <React.Suspense fallback={null}>
3247
+ <Component />
3248
+ </React.Suspense>
3249
+ );
3250
+ };
3251
+ };
3252
+
3253
+ export const AddToCart = lazyRemote('checkout/AddToCart');
3254
+ export const Recommendations = lazyRemote('explore/Recommendations');
3255
+ `;
3256
+ }
3195
3257
  function remoteComponentOutputPath(app, expose) {
3196
3258
  const exposePath = app.exposes?.[expose];
3197
3259
  if (!exposePath?.startsWith('./src/components/')) return;
@@ -5319,6 +5381,7 @@ function writeApp(targetDir, scope, app, packageSource, enableTailwind) {
5319
5381
  for (const routePath of routePaths)if ('/' !== routePath) writeFile(targetDir, createRoutePageFilePath(app, routePath), createRouteAliasPage(routePath));
5320
5382
  }
5321
5383
  if ('shell' === app.kind) {
5384
+ writeFile(targetDir, `${app.directory}/src/routes/remote-components.tsx`, createShellRemoteComponents());
5322
5385
  writeFile(targetDir, `${app.directory}/src/effect/recommendations-client.ts`, createShellEffectClient(scope));
5323
5386
  writeFile(targetDir, `${app.directory}/src/routes/[lang]/tractors/page.tsx`, createShellTractorsPage());
5324
5387
  writeFile(targetDir, `${app.directory}/src/routes/[lang]/traktory/page.tsx`, createShellTractorsPage());
@@ -5334,6 +5397,7 @@ function writeApp(targetDir, scope, app, packageSource, enableTailwind) {
5334
5397
  }
5335
5398
  if ('vertical' === app.kind || 'horizontal-remote' === app.kind) {
5336
5399
  writeFile(targetDir, `${app.directory}/src/remote-entry.tsx`, createRemoteEntry(app));
5400
+ if ('remote-decide' === app.id) writeFile(targetDir, `${app.directory}/src/components/remote-components.tsx`, createDecideRemoteComponents());
5337
5401
  if ('remote-checkout' === app.id) writeFile(targetDir, `${app.directory}/src/cart-store.ts`, createCheckoutCartStore());
5338
5402
  for (const expose of Object.keys(app.exposes ?? {})){
5339
5403
  const outputPath = remoteComponentOutputPath(app, expose);
package/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "engines": {
22
22
  "node": ">=20"
23
23
  },
24
- "version": "3.2.0-ultramodern.37",
24
+ "version": "3.2.0-ultramodern.39",
25
25
  "types": "./dist/types/index.d.ts",
26
26
  "main": "./dist/index.js",
27
27
  "bin": {
@@ -41,7 +41,7 @@
41
41
  "@types/node": "^25.9.1",
42
42
  "@typescript/native-preview": "7.0.0-dev.20260527.2",
43
43
  "tsx": "^4.22.3",
44
- "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.2.0-ultramodern.37"
44
+ "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.2.0-ultramodern.39"
45
45
  },
46
46
  "publishConfig": {
47
47
  "registry": "https://registry.npmjs.org/",
@@ -54,6 +54,6 @@
54
54
  "start": "node ./dist/index.js"
55
55
  },
56
56
  "ultramodern": {
57
- "frameworkVersion": "3.2.0-ultramodern.37"
57
+ "frameworkVersion": "3.2.0-ultramodern.39"
58
58
  }
59
59
  }
@@ -17,6 +17,14 @@ const run = (command, args, options = {}) =>
17
17
  stdio: options.stdio ?? ['ignore', 'pipe', 'pipe'],
18
18
  });
19
19
 
20
+ const removeTree = (dir) =>
21
+ fs.rmSync(dir, {
22
+ force: true,
23
+ maxRetries: 5,
24
+ recursive: true,
25
+ retryDelay: 100,
26
+ });
27
+
20
28
  const cloneSource = (source, targetDir) => {
21
29
  const repo = source.repository.replace(/^https:\/\/github.com\//u, '');
22
30
  try {
@@ -84,12 +92,12 @@ for (const source of privateSources) {
84
92
  console.log(`Skipping existing ${skill.name}`);
85
93
  continue;
86
94
  }
87
- fs.rmSync(targetSkillDir, { force: true, recursive: true });
95
+ removeTree(targetSkillDir);
88
96
  }
89
97
  fs.cpSync(sourceSkillDir, targetSkillDir, { recursive: true });
90
98
  console.log(`Installed ${skill.name}`);
91
99
  }
92
100
  } finally {
93
- fs.rmSync(tempDir, { force: true, recursive: true });
101
+ removeTree(tempDir);
94
102
  }
95
103
  }
@@ -17,6 +17,14 @@ const run = (command, args, options = {}) =>
17
17
  stdio: options.stdio ?? ['ignore', 'pipe', 'pipe'],
18
18
  });
19
19
 
20
+ const removeTree = dir =>
21
+ fs.rmSync(dir, {
22
+ force: true,
23
+ maxRetries: 5,
24
+ recursive: true,
25
+ retryDelay: 100,
26
+ });
27
+
20
28
  const cloneSource = (source, targetDir) => {
21
29
  const repo = source.repository.replace(/^https:\/\/github.com\//u, '');
22
30
  try {
@@ -144,12 +152,12 @@ for (const source of [...requiredCloneSources, ...optionalCloneSources]) {
144
152
  console.log(`Skipping existing ${skill.name}`);
145
153
  continue;
146
154
  }
147
- fs.rmSync(targetSkillDir, { force: true, recursive: true });
155
+ removeTree(targetSkillDir);
148
156
  }
149
157
  fs.cpSync(sourceSkillDir, targetSkillDir, { recursive: true });
150
158
  console.log(`Installed ${skill.name}`);
151
159
  }
152
160
  } finally {
153
- fs.rmSync(tempDir, { force: true, recursive: true });
161
+ removeTree(tempDir);
154
162
  }
155
163
  }