@bleedingdev/modern-js-create 3.2.0-ultramodern.31 → 3.2.0-ultramodern.32

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
@@ -607,6 +607,9 @@ const modernPackageNames = [
607
607
  '@modern-js/runtime'
608
608
  ];
609
609
  const ULTRAMODERN_WORKSPACE_FLAG = '--ultramodern-workspace';
610
+ function isRecord(value) {
611
+ return null !== value && 'object' == typeof value && !Array.isArray(value);
612
+ }
610
613
  const shellApp = {
611
614
  id: 'shell-super-app',
612
615
  directory: 'apps/shell-super-app',
@@ -617,9 +620,9 @@ const shellApp = {
617
620
  port: 3020,
618
621
  mfName: 'shellSuperApp',
619
622
  remoteRefs: [
620
- 'remote-commerce',
621
- 'remote-identity',
622
- 'remote-design-system'
623
+ 'remote-explore',
624
+ 'remote-decide',
625
+ 'remote-checkout'
623
626
  ],
624
627
  ownership: {
625
628
  team: 'super-app-platform',
@@ -638,104 +641,123 @@ const shellApp = {
638
641
  };
639
642
  const remoteApps = [
640
643
  {
641
- id: 'remote-commerce',
642
- directory: 'apps/remotes/remote-commerce',
643
- packageSuffix: 'remote-commerce',
644
- displayName: 'Commerce Remote',
644
+ id: 'remote-explore',
645
+ directory: 'apps/remotes/remote-explore',
646
+ packageSuffix: 'remote-explore',
647
+ displayName: 'Explore Remote',
645
648
  kind: 'vertical',
646
- domain: 'commerce',
647
- portEnv: 'REMOTE_COMMERCE_PORT',
649
+ domain: 'explore',
650
+ portEnv: 'REMOTE_EXPLORE_PORT',
648
651
  port: 3021,
649
- mfName: 'remoteCommerce',
652
+ mfName: 'remoteExplore',
650
653
  exposes: {
654
+ './Footer': './src/components/footer.tsx',
655
+ './Header': './src/components/header.tsx',
656
+ './Recommendations': './src/components/recommendations.tsx',
651
657
  './Route': './src/remote-entry.tsx',
652
- './Widget': './src/components/commerce-widget.tsx'
658
+ './StorePicker': './src/components/store-picker.tsx'
653
659
  },
654
660
  effectApi: {
655
- stem: 'recommendations',
656
- prefix: '/commerce-api',
661
+ stem: 'explore',
662
+ prefix: '/explore-api',
657
663
  consumedBy: [
658
664
  shellApp.id,
659
- 'remote-commerce'
665
+ 'remote-explore'
660
666
  ]
661
667
  },
662
668
  ownership: {
663
- team: 'commerce-experience',
664
- slack: '#commerce-experience',
665
- pagerDuty: 'pd-commerce-experience',
666
- runbookRef: 'runbooks/wave2/remote-commerce.md',
667
- adrRef: 'docs/super-app-rfc-adr/wave2/reference-topology.md#remote-commerce',
669
+ team: 'tractor-explore',
670
+ slack: '#tractor-explore',
671
+ pagerDuty: 'pd-tractor-explore',
672
+ runbookRef: 'runbooks/wave2/remote-explore.md',
673
+ adrRef: 'docs/super-app-rfc-adr/wave2/reference-topology.md#remote-explore',
668
674
  blastRadius: {
669
- tier: 'tier-1-revenue-path',
675
+ tier: 'tier-1-tractor-discovery',
670
676
  references: [
671
- 'docs/super-app-rfc-adr/wave2/blast-radius.md#commerce',
672
- 'docs/super-app-rfc-adr/wave2/rollback.md#commerce-lkg'
677
+ 'docs/super-app-rfc-adr/wave2/blast-radius.md#explore',
678
+ 'docs/super-app-rfc-adr/wave2/rollback.md#explore-lkg'
673
679
  ]
674
680
  }
675
681
  }
676
682
  },
677
683
  {
678
- id: 'remote-identity',
679
- directory: 'apps/remotes/remote-identity',
680
- packageSuffix: 'remote-identity',
681
- displayName: 'Identity Remote',
684
+ id: 'remote-decide',
685
+ directory: 'apps/remotes/remote-decide',
686
+ packageSuffix: 'remote-decide',
687
+ displayName: 'Decide Remote',
682
688
  kind: 'vertical',
683
- domain: 'identity',
684
- portEnv: 'REMOTE_IDENTITY_PORT',
689
+ domain: 'decide',
690
+ portEnv: 'REMOTE_DECIDE_PORT',
685
691
  port: 3022,
686
- mfName: 'remoteIdentity',
692
+ mfName: 'remoteDecide',
693
+ remoteRefs: [
694
+ 'remote-explore',
695
+ 'remote-checkout'
696
+ ],
687
697
  exposes: {
688
- './Route': './src/remote-entry.tsx',
689
- './Widget': './src/components/identity-widget.tsx'
698
+ './ProductPage': './src/components/product-page.tsx',
699
+ './Route': './src/remote-entry.tsx'
690
700
  },
691
701
  effectApi: {
692
- stem: 'identity',
693
- prefix: '/identity-api',
702
+ stem: 'decide',
703
+ prefix: '/decide-api',
694
704
  consumedBy: [
695
705
  shellApp.id,
696
- 'remote-identity'
706
+ 'remote-decide'
697
707
  ]
698
708
  },
699
709
  ownership: {
700
- team: 'identity-platform',
701
- slack: '#identity-platform',
702
- pagerDuty: 'pd-identity-platform',
703
- runbookRef: 'runbooks/wave2/remote-identity.md',
704
- adrRef: 'docs/super-app-rfc-adr/wave2/reference-topology.md#remote-identity',
710
+ team: 'tractor-decide',
711
+ slack: '#tractor-decide',
712
+ pagerDuty: 'pd-tractor-decide',
713
+ runbookRef: 'runbooks/wave2/remote-decide.md',
714
+ adrRef: 'docs/super-app-rfc-adr/wave2/reference-topology.md#remote-decide',
705
715
  blastRadius: {
706
- tier: 'tier-0-authentication',
716
+ tier: 'tier-1-tractor-configuration',
707
717
  references: [
708
- 'docs/super-app-rfc-adr/wave2/blast-radius.md#identity',
709
- 'docs/super-app-rfc-adr/wave2/rollback.md#identity-lkg'
718
+ 'docs/super-app-rfc-adr/wave2/blast-radius.md#decide',
719
+ 'docs/super-app-rfc-adr/wave2/rollback.md#decide-lkg'
710
720
  ]
711
721
  }
712
722
  }
713
723
  },
714
724
  {
715
- id: 'remote-design-system',
716
- directory: 'apps/remotes/remote-design-system',
717
- packageSuffix: 'remote-design-system',
718
- displayName: 'Design System Remote',
719
- kind: 'horizontal-design-system',
720
- domain: 'design-system',
721
- portEnv: 'REMOTE_DESIGN_SYSTEM_PORT',
725
+ id: 'remote-checkout',
726
+ directory: 'apps/remotes/remote-checkout',
727
+ packageSuffix: 'remote-checkout',
728
+ displayName: 'Checkout Remote',
729
+ kind: 'vertical',
730
+ domain: 'checkout',
731
+ portEnv: 'REMOTE_CHECKOUT_PORT',
722
732
  port: 3023,
723
- mfName: 'remoteDesignSystem',
733
+ mfName: 'remoteCheckout',
724
734
  exposes: {
725
- './Button': './src/components/button.tsx',
726
- './tokens': './src/tokens.ts'
735
+ './AddToCart': './src/components/add-to-cart.tsx',
736
+ './CartPage': './src/components/cart-page.tsx',
737
+ './CheckoutPage': './src/components/checkout-page.tsx',
738
+ './MiniCart': './src/components/mini-cart.tsx',
739
+ './Route': './src/remote-entry.tsx',
740
+ './ThanksPage': './src/components/thanks-page.tsx'
741
+ },
742
+ effectApi: {
743
+ stem: 'checkout',
744
+ prefix: '/checkout-api',
745
+ consumedBy: [
746
+ shellApp.id,
747
+ 'remote-checkout'
748
+ ]
727
749
  },
728
750
  ownership: {
729
- team: 'design-platform',
730
- slack: '#design-platform',
731
- pagerDuty: 'pd-design-platform',
732
- runbookRef: 'runbooks/wave2/remote-design-system.md',
733
- adrRef: 'docs/super-app-rfc-adr/wave2/reference-topology.md#remote-design-system',
751
+ team: 'tractor-checkout',
752
+ slack: '#tractor-checkout',
753
+ pagerDuty: 'pd-tractor-checkout',
754
+ runbookRef: 'runbooks/wave2/remote-checkout.md',
755
+ adrRef: 'docs/super-app-rfc-adr/wave2/reference-topology.md#remote-checkout',
734
756
  blastRadius: {
735
- tier: 'tier-0-shared-ui',
757
+ tier: 'tier-1-tractor-purchase',
736
758
  references: [
737
- 'docs/super-app-rfc-adr/wave2/blast-radius.md#design-system',
738
- 'docs/super-app-rfc-adr/wave2/rollback.md#design-system-pins'
759
+ 'docs/super-app-rfc-adr/wave2/blast-radius.md#checkout',
760
+ 'docs/super-app-rfc-adr/wave2/rollback.md#checkout-lkg'
739
761
  ]
740
762
  }
741
763
  }
@@ -1100,11 +1122,11 @@ function createRootPackageJson(scope, packageSource) {
1100
1122
  type: 'module',
1101
1123
  packageManager: `pnpm@${PNPM_VERSION}`,
1102
1124
  scripts: {
1103
- dev: `pnpm --parallel --filter ${ultramodern_workspace_packageName(scope, shellApp.packageSuffix)} --filter ${ultramodern_workspace_packageName(scope, 'remote-commerce')} --filter ${ultramodern_workspace_packageName(scope, 'remote-identity')} --filter ${ultramodern_workspace_packageName(scope, 'remote-design-system')} dev`,
1125
+ dev: `pnpm --parallel --filter ${ultramodern_workspace_packageName(scope, shellApp.packageSuffix)} --filter ${ultramodern_workspace_packageName(scope, 'remote-explore')} --filter ${ultramodern_workspace_packageName(scope, 'remote-decide')} --filter ${ultramodern_workspace_packageName(scope, 'remote-checkout')} dev`,
1104
1126
  'dev:shell': `pnpm --filter ${ultramodern_workspace_packageName(scope, shellApp.packageSuffix)} dev`,
1105
- 'dev:commerce': `pnpm --filter ${ultramodern_workspace_packageName(scope, 'remote-commerce')} dev`,
1106
- 'dev:identity': `pnpm --filter ${ultramodern_workspace_packageName(scope, 'remote-identity')} dev`,
1107
- 'dev:design-system': `pnpm --filter ${ultramodern_workspace_packageName(scope, 'remote-design-system')} dev`,
1127
+ 'dev:explore': `pnpm --filter ${ultramodern_workspace_packageName(scope, 'remote-explore')} dev`,
1128
+ 'dev:decide': `pnpm --filter ${ultramodern_workspace_packageName(scope, 'remote-decide')} dev`,
1129
+ 'dev:checkout': `pnpm --filter ${ultramodern_workspace_packageName(scope, 'remote-checkout')} dev`,
1108
1130
  build: 'pnpm -r --filter "./apps/remotes/**" run build && pnpm --filter "./apps/shell-super-app" run build && pnpm ultramodern:assert-mf-types',
1109
1131
  format: 'oxfmt .',
1110
1132
  'format:check': 'oxfmt --check .',
@@ -1112,6 +1134,8 @@ function createRootPackageJson(scope, packageSource) {
1112
1134
  'lint:fix': 'oxlint . --fix',
1113
1135
  typecheck: `pnpm -r --filter "@${scope}/*" typecheck`,
1114
1136
  'cloudflare:build': 'pnpm -r --filter "./apps/remotes/**" run cloudflare:build && pnpm --filter "./apps/shell-super-app" run cloudflare:build && pnpm ultramodern:assert-mf-types',
1137
+ 'cloudflare:deploy': 'pnpm -r --filter "./apps/remotes/**" run cloudflare:deploy && pnpm --filter "./apps/shell-super-app" run cloudflare:deploy',
1138
+ 'cloudflare:proof': "node ./scripts/proof-cloudflare-version.mjs --out .codex/reports/cloudflare-version-proof/public-url-proof.json",
1115
1139
  'skills:install': "node ./scripts/bootstrap-agent-skills.mjs",
1116
1140
  'skills:check': "node ./scripts/bootstrap-agent-skills.mjs --check",
1117
1141
  'agents:refs:install': "node ./scripts/setup-agent-reference-repos.mjs",
@@ -1158,13 +1182,61 @@ function remoteDependencyAlias(remote) {
1158
1182
  function zephyrRemoteDependency(scope, remote) {
1159
1183
  return `${ultramodern_workspace_packageName(scope, remote.packageSuffix)}@workspace:*`;
1160
1184
  }
1185
+ function resolveRemoteRefs(app, remotes = remoteApps) {
1186
+ const remoteRefs = app.remoteRefs ?? [];
1187
+ return remoteRefs.map((remoteRef)=>remotes.find((remote)=>remote.id === remoteRef)).filter((remote)=>void 0 !== remote);
1188
+ }
1189
+ function createModuleFederationRemoteContracts(app, remotes = remoteApps) {
1190
+ return resolveRemoteRefs(app, remotes).map((remote)=>({
1191
+ id: remote.id,
1192
+ alias: remoteDependencyAlias(remote),
1193
+ name: remote.mfName,
1194
+ manifestEnv: createRemoteManifestEnv(remote),
1195
+ manifestUrl: `http://localhost:${remote.port}/mf-manifest.json`
1196
+ }));
1197
+ }
1161
1198
  function createZephyrDependencies(scope, app, remotes = remoteApps) {
1162
- if ('shell' !== app.kind) return {};
1163
- return Object.fromEntries(remotes.map((remote)=>[
1199
+ if (!app.remoteRefs?.length) return {};
1200
+ return Object.fromEntries(resolveRemoteRefs(app, remotes).map((remote)=>[
1164
1201
  remoteDependencyAlias(remote),
1165
1202
  zephyrRemoteDependency(scope, remote)
1166
1203
  ]));
1167
1204
  }
1205
+ function createCloudflareWorkerName(scope, app) {
1206
+ return toKebabCase(`${scope}-${app.packageSuffix}`).slice(0, 63);
1207
+ }
1208
+ function createCloudflarePublicUrlEnv(app) {
1209
+ return `ULTRAMODERN_PUBLIC_URL_${toEnvSegment(app.id)}`;
1210
+ }
1211
+ function createCloudflareProofRoute(app) {
1212
+ const languageRoutes = createLocalisedUrlsMap(app);
1213
+ const firstCanonicalPath = Object.keys(languageRoutes)[0];
1214
+ const localizedPath = firstCanonicalPath && isRecord(languageRoutes[firstCanonicalPath]) ? languageRoutes[firstCanonicalPath].en : void 0;
1215
+ return {
1216
+ ssr: localizedPath ?? '/en',
1217
+ mfManifest: '/mf-manifest.json',
1218
+ locale: `/locales/en/${appI18nNamespace(app)}.json`,
1219
+ ...appHasEffectApi(app) ? {
1220
+ effectReadiness: `${effectApiPrefix(app)}/effect/${effectApiStem(app)}/readiness`
1221
+ } : {}
1222
+ };
1223
+ }
1224
+ function createCloudflareDeployContract(scope, app) {
1225
+ return {
1226
+ target: 'cloudflare',
1227
+ workerName: createCloudflareWorkerName(scope, app),
1228
+ publicUrlEnv: createCloudflarePublicUrlEnv(app),
1229
+ compatibilityFlags: [
1230
+ 'nodejs_compat'
1231
+ ],
1232
+ assetsBinding: 'ASSETS',
1233
+ routes: createCloudflareProofRoute(app),
1234
+ evidence: {
1235
+ proofScript: "scripts/proof-cloudflare-version.mjs",
1236
+ reportDefault: '.codex/reports/cloudflare-version-proof/public-url-proof.json'
1237
+ }
1238
+ };
1239
+ }
1168
1240
  function createTsConfigBase() {
1169
1241
  return {
1170
1242
  compilerOptions: {
@@ -1234,7 +1306,9 @@ function createAppPackage(scope, app, packageSource, enableTailwind) {
1234
1306
  dev: 'modern dev',
1235
1307
  build: app.exposes ? `modern build && node ${relativeRootFor(app.directory)}/scripts/assert-mf-types.mjs` : 'modern build',
1236
1308
  'cloudflare:build': 'MODERNJS_DEPLOY=cloudflare modern build && MODERNJS_DEPLOY=cloudflare modern deploy',
1309
+ 'cloudflare:deploy': 'MODERNJS_DEPLOY=cloudflare modern deploy',
1237
1310
  'cloudflare:preview': 'MODERNJS_DEPLOY=cloudflare modern build && MODERNJS_DEPLOY=cloudflare modern deploy && wrangler dev --config .output/wrangler.json',
1311
+ 'cloudflare:proof': `node ${relativeRootFor(app.directory)}/scripts/proof-cloudflare-version.mjs --app ${app.id}`,
1238
1312
  serve: 'modern serve',
1239
1313
  typecheck: effectTsgoTypecheckCommand
1240
1314
  },
@@ -1255,6 +1329,9 @@ function createAppPackage(scope, app, packageSource, enableTailwind) {
1255
1329
  './effect/client': `./src/effect/${app.effectApi.stem}-client.ts`,
1256
1330
  './shared/effect/api': './shared/effect/api.ts'
1257
1331
  };
1332
+ else if ('shell' === app.kind) packageJson.exports = {
1333
+ './effect/clients': './src/effect/recommendations-client.ts'
1334
+ };
1258
1335
  return packageJson;
1259
1336
  }
1260
1337
  function createServicePackage(scope, packageSource, enableTailwind, service = effectService) {
@@ -1315,12 +1392,16 @@ function createSharedPackage(scope, id, description, packageSource) {
1315
1392
  "@typescript/native-preview": TYPESCRIPT_NATIVE_PREVIEW_VERSION
1316
1393
  }
1317
1394
  };
1395
+ if ('shared-design-tokens' === id) packageJson.exports = {
1396
+ ...packageJson.exports,
1397
+ './tokens.css': './src/tokens.css'
1398
+ };
1318
1399
  if ('shared-effect-api' === id) packageJson.dependencies = {
1319
1400
  '@modern-js/plugin-bff': modernPackageSpecifier('@modern-js/plugin-bff', packageSource)
1320
1401
  };
1321
1402
  return packageJson;
1322
1403
  }
1323
- function createAppModernConfig(app) {
1404
+ function createAppModernConfig(scope, app) {
1324
1405
  const bffImport = appHasEffectApi(app) ? "import { bffPlugin } from '@modern-js/plugin-bff';\n" : '';
1325
1406
  const bffConfig = appHasEffectApi(app) ? ` bff: {
1326
1407
  effect: {
@@ -1343,6 +1424,7 @@ ${bffImport}import { i18nPlugin } from '@modern-js/plugin-i18n';
1343
1424
  import { tanstackRouterPlugin } from '@modern-js/plugin-tanstack';
1344
1425
  import { moduleFederationPlugin } from '@module-federation/modern-js-v3';
1345
1426
  import { withZephyr as withZephyrRspack } from 'zephyr-rspack-plugin';
1427
+ import { ultramodernLocalisedUrls } from './src/routes/ultramodern-route-metadata';
1346
1428
 
1347
1429
  type ZephyrRspackConfig = Parameters<ReturnType<typeof withZephyrRspack>>[0];
1348
1430
 
@@ -1361,6 +1443,7 @@ const zephyrRspackPlugin = () => ({
1361
1443
  });
1362
1444
 
1363
1445
  const appId = '${app.id}';
1446
+ const cloudflareWorkerName = '${createCloudflareWorkerName(scope, app)}';
1364
1447
  const port = Number(process.env['${app.portEnv}'] ?? ${app.port});
1365
1448
  const configuredSiteUrl = process.env['MODERN_PUBLIC_SITE_URL'];
1366
1449
  const hasConfiguredSiteUrl =
@@ -1403,13 +1486,14 @@ ${bffConfig} output: {
1403
1486
  tanstackRouterPlugin(),
1404
1487
  i18nPlugin({
1405
1488
  backend: {
1406
- enabled: false,
1489
+ enabled: true,
1407
1490
  },
1408
1491
  reactI18next: false,
1409
1492
  localeDetection: {
1410
1493
  fallbackLanguage: 'en',
1411
1494
  languages: ['en', 'cs'],
1412
1495
  localePathRedirect: true,
1496
+ localisedUrls: ultramodernLocalisedUrls as Record<string, Record<string, string>>,
1413
1497
  ignoreRedirectRoutes: [
1414
1498
  '/@mf-types',
1415
1499
  '/bundles',
@@ -1442,6 +1526,7 @@ ${bffPluginEntry} moduleFederationPlugin(),
1442
1526
  deploy: {
1443
1527
  target: 'cloudflare',
1444
1528
  worker: {
1529
+ name: cloudflareWorkerName,
1445
1530
  ssr: true,
1446
1531
  },
1447
1532
  },
@@ -1510,13 +1595,24 @@ ${entries.map(([key, entryValue])=>` '${key}': '${entryValue}',`).join('\n')}
1510
1595
  function createRemoteManifestEnv(remote) {
1511
1596
  return `REMOTE_${toEnvSegment(remote.domain ?? remote.id)}_MF_MANIFEST`;
1512
1597
  }
1513
- function createShellModuleFederationConfig(remotes = remoteApps) {
1514
- const remoteEntries = remotes.map((remote)=>{
1598
+ function createModuleFederationRemotesConfig(app, remotes = remoteApps) {
1599
+ const remoteEntries = resolveRemoteRefs(app, remotes).map((remote)=>{
1515
1600
  const key = remoteDependencyAlias(remote);
1516
1601
  return ` ${key}:
1517
1602
  process.env['${createRemoteManifestEnv(remote)}'] ??
1518
1603
  '${remote.mfName}@http://localhost:${remote.port}/mf-manifest.json',`;
1519
1604
  }).join('\n');
1605
+ if (!remoteEntries) return '';
1606
+ return ` remotes: {
1607
+ ${remoteEntries}
1608
+ },
1609
+ `;
1610
+ }
1611
+ function createShellModuleFederationConfig(remotes = remoteApps) {
1612
+ const shellHost = {
1613
+ ...shellApp,
1614
+ remoteRefs: remotes.map((remote)=>remote.id)
1615
+ };
1520
1616
  return `// @effect-diagnostics nodeBuiltinImport:off processEnv:off
1521
1617
  import { createRequire } from 'node:module';
1522
1618
  import { createModuleFederationConfig } from '@module-federation/modern-js-v3';
@@ -1540,10 +1636,7 @@ export default createModuleFederationConfig({
1540
1636
  },
1541
1637
  filename: 'remoteEntry.js',
1542
1638
  name: '${shellApp.mfName}',
1543
- remotes: {
1544
- ${remoteEntries}
1545
- },
1546
- ${createSharedModuleFederationConfig()},
1639
+ ${createModuleFederationRemotesConfig(shellHost, remotes)}${createSharedModuleFederationConfig()},
1547
1640
  });
1548
1641
  `;
1549
1642
  }
@@ -1570,7 +1663,7 @@ export const ultramodernApiMarker = {
1570
1663
  } as const;
1571
1664
  `;
1572
1665
  }
1573
- function createRemoteModuleFederationConfig(app) {
1666
+ function createRemoteModuleFederationConfig(app, remotes = remoteApps) {
1574
1667
  const exposes = formatTsObjectLiteral(app.exposes ?? {});
1575
1668
  return `// @effect-diagnostics nodeBuiltinImport:off
1576
1669
  import { createRequire } from 'node:module';
@@ -1596,12 +1689,248 @@ export default createModuleFederationConfig({
1596
1689
  exposes: ${exposes},
1597
1690
  filename: 'remoteEntry.js',
1598
1691
  name: '${app.mfName}',
1599
- ${createSharedModuleFederationConfig()},
1692
+ ${createModuleFederationRemotesConfig(app, remotes)}${createSharedModuleFederationConfig()},
1600
1693
  });
1601
1694
  `;
1602
1695
  }
1603
- function remoteWidgetFile(app) {
1604
- return `${app.domain ?? app.id.replace(/^remote-/, '')}-widget`;
1696
+ function appI18nNamespace(app) {
1697
+ return 'shell' === app.kind ? 'shell' : app.domain ?? app.id;
1698
+ }
1699
+ function createRouteOwnedI18nPaths(app) {
1700
+ const namespace = appI18nNamespace(app);
1701
+ const base = {
1702
+ mfBoundaryId: app.mfName,
1703
+ namespace,
1704
+ ownerAppId: app.id
1705
+ };
1706
+ if ('shell' === app.kind) return [
1707
+ {
1708
+ ...base,
1709
+ canonicalPath: '/',
1710
+ id: 'shell-home',
1711
+ localisedPaths: {
1712
+ cs: '/',
1713
+ en: '/'
1714
+ },
1715
+ titleKey: 'shell.title'
1716
+ }
1717
+ ];
1718
+ if ('explore' === app.domain) return [
1719
+ {
1720
+ ...base,
1721
+ canonicalPath: '/',
1722
+ id: 'explore-home',
1723
+ localisedPaths: {
1724
+ cs: '/',
1725
+ en: '/'
1726
+ },
1727
+ titleKey: 'explore.title'
1728
+ },
1729
+ {
1730
+ ...base,
1731
+ canonicalPath: '/tractors',
1732
+ id: 'explore-listing',
1733
+ localisedPaths: {
1734
+ cs: '/traktory',
1735
+ en: '/tractors'
1736
+ },
1737
+ titleKey: 'explore.routes.listing'
1738
+ },
1739
+ {
1740
+ ...base,
1741
+ canonicalPath: '/stores',
1742
+ id: 'explore-store-picker',
1743
+ localisedPaths: {
1744
+ cs: '/prodejci',
1745
+ en: '/stores'
1746
+ },
1747
+ titleKey: 'explore.routes.storePicker'
1748
+ },
1749
+ {
1750
+ ...base,
1751
+ canonicalPath: '/unavailable',
1752
+ id: 'explore-unavailable',
1753
+ localisedPaths: {
1754
+ cs: '/nedostupne',
1755
+ en: '/unavailable'
1756
+ },
1757
+ titleKey: 'explore.routes.unavailable'
1758
+ }
1759
+ ];
1760
+ if ('decide' === app.domain) return [
1761
+ {
1762
+ ...base,
1763
+ canonicalPath: '/',
1764
+ id: 'decide-home',
1765
+ localisedPaths: {
1766
+ cs: '/',
1767
+ en: '/'
1768
+ },
1769
+ titleKey: 'decide.title'
1770
+ },
1771
+ {
1772
+ ...base,
1773
+ canonicalPath: '/tractors',
1774
+ id: 'decide-listing-parent',
1775
+ localisedPaths: {
1776
+ cs: '/traktory',
1777
+ en: '/tractors'
1778
+ },
1779
+ titleKey: 'decide.routes.listing'
1780
+ },
1781
+ {
1782
+ ...base,
1783
+ canonicalPath: '/tractors/:slug',
1784
+ id: 'decide-product-detail',
1785
+ localisedPaths: {
1786
+ cs: '/traktory/:slug',
1787
+ en: '/tractors/:slug'
1788
+ },
1789
+ titleKey: 'decide.routes.productDetail'
1790
+ },
1791
+ {
1792
+ ...base,
1793
+ canonicalPath: '/unavailable',
1794
+ id: 'decide-unavailable',
1795
+ localisedPaths: {
1796
+ cs: '/nedostupne',
1797
+ en: '/unavailable'
1798
+ },
1799
+ titleKey: 'decide.routes.unavailable'
1800
+ }
1801
+ ];
1802
+ if ('checkout' === app.domain) return [
1803
+ {
1804
+ ...base,
1805
+ canonicalPath: '/',
1806
+ id: 'checkout-home',
1807
+ localisedPaths: {
1808
+ cs: '/',
1809
+ en: '/'
1810
+ },
1811
+ titleKey: 'checkout.title'
1812
+ },
1813
+ {
1814
+ ...base,
1815
+ canonicalPath: '/cart',
1816
+ id: 'checkout-cart',
1817
+ localisedPaths: {
1818
+ cs: '/kosik',
1819
+ en: '/cart'
1820
+ },
1821
+ titleKey: 'checkout.routes.cart'
1822
+ },
1823
+ {
1824
+ ...base,
1825
+ canonicalPath: '/checkout',
1826
+ id: 'checkout-start',
1827
+ localisedPaths: {
1828
+ cs: '/pokladna',
1829
+ en: '/checkout'
1830
+ },
1831
+ titleKey: 'checkout.routes.checkout'
1832
+ },
1833
+ {
1834
+ ...base,
1835
+ canonicalPath: '/checkout/thank-you',
1836
+ id: 'checkout-thank-you-parent',
1837
+ localisedPaths: {
1838
+ cs: '/pokladna/dekujeme',
1839
+ en: '/checkout/thank-you'
1840
+ },
1841
+ titleKey: 'checkout.routes.thankYou'
1842
+ },
1843
+ {
1844
+ ...base,
1845
+ canonicalPath: '/checkout/thank-you/:orderId?',
1846
+ id: 'checkout-thank-you',
1847
+ localisedPaths: {
1848
+ cs: '/pokladna/dekujeme/:orderId?',
1849
+ en: '/checkout/thank-you/:orderId?'
1850
+ },
1851
+ titleKey: 'checkout.routes.thankYou'
1852
+ },
1853
+ {
1854
+ ...base,
1855
+ canonicalPath: '/unavailable',
1856
+ id: 'checkout-unavailable',
1857
+ localisedPaths: {
1858
+ cs: '/nedostupne',
1859
+ en: '/unavailable'
1860
+ },
1861
+ titleKey: 'checkout.routes.unavailable'
1862
+ }
1863
+ ];
1864
+ return [
1865
+ {
1866
+ ...base,
1867
+ canonicalPath: '/',
1868
+ id: `${app.id}-home`,
1869
+ localisedPaths: {
1870
+ cs: '/',
1871
+ en: '/'
1872
+ },
1873
+ titleKey: `${namespace}.title`
1874
+ }
1875
+ ];
1876
+ }
1877
+ function createLocalisedUrlsMap(app) {
1878
+ return Object.fromEntries(createRouteOwnedI18nPaths(app).filter((route)=>'/' !== route.canonicalPath).map((route)=>[
1879
+ route.canonicalPath,
1880
+ route.localisedPaths
1881
+ ]));
1882
+ }
1883
+ function createRouteMetadataModule(app) {
1884
+ const routes = createRouteOwnedI18nPaths(app);
1885
+ const localisedUrls = createLocalisedUrlsMap(app);
1886
+ const namespace = appI18nNamespace(app);
1887
+ return `export const ultramodernRouteNamespace = '${namespace}' as const;
1888
+
1889
+ export const ultramodernRouteMetadata = ${JSON.stringify(routes, null, 2)} as const;
1890
+
1891
+ export const ultramodernLocalisedUrls = ${JSON.stringify(localisedUrls, null, 2)} as const;
1892
+
1893
+ export const ultramodernRouteConfig = {
1894
+ source: 'route-owned',
1895
+ namespace: ultramodernRouteNamespace,
1896
+ localisedUrls: ultramodernLocalisedUrls,
1897
+ routes: ultramodernRouteMetadata,
1898
+ } as const;
1899
+ `;
1900
+ }
1901
+ function routeSegmentToDirectory(segment) {
1902
+ if (segment.startsWith(':')) {
1903
+ const name = segment.slice(1).replace(/\?$/u, '');
1904
+ return segment.endsWith('?') ? `[${name}$]` : `[${name}]`;
1905
+ }
1906
+ return segment;
1907
+ }
1908
+ function createRoutePageFilePath(app, canonicalPath) {
1909
+ const segments = canonicalPath.split('/').filter(Boolean).map(routeSegmentToDirectory);
1910
+ return `${app.directory}/src/routes/[lang]/${[
1911
+ ...segments,
1912
+ 'page.tsx'
1913
+ ].join('/')}`;
1914
+ }
1915
+ function createRouteAliasPage(canonicalPath) {
1916
+ const depth = canonicalPath.split('/').filter(Boolean).length;
1917
+ const rootPageImport = `${'../'.repeat(depth)}page`;
1918
+ return `export { default } from '${rootPageImport}';
1919
+ `;
1920
+ }
1921
+ function createAppEnvDts(app, remotes = remoteApps) {
1922
+ const remoteModuleDeclarations = resolveRemoteRefs(app, remotes).flatMap((remote)=>Object.keys(remote.exposes ?? {}).filter((expose)=>'./Route' !== expose).map((expose)=>{
1923
+ const moduleName = `${remoteDependencyAlias(remote)}/${expose.replace(/^\.\//u, '')}`;
1924
+ return `declare module '${moduleName}' {
1925
+ const Component: import('react').ComponentType<Record<string, never>>;
1926
+ export default Component;
1927
+ }
1928
+ `;
1929
+ })).join('\n');
1930
+ return `/// <reference types='@modern-js/app-tools/types' />
1931
+
1932
+ declare const ULTRAMODERN_SITE_URL: string;
1933
+ ${remoteModuleDeclarations ? `\n${remoteModuleDeclarations}` : ''}`;
1605
1934
  }
1606
1935
  function createServiceModernConfigFor(service = effectService) {
1607
1936
  return `// @effect-diagnostics processEnv:off
@@ -1639,16 +1968,20 @@ export default defineConfig(
1639
1968
  `;
1640
1969
  }
1641
1970
  function createAppRuntimeConfig(app) {
1971
+ const namespace = appI18nNamespace(app);
1642
1972
  const resources = {
1643
1973
  cs: {
1974
+ [namespace]: createAppLocaleMessages(app, 'cs'),
1644
1975
  translation: createAppLocaleMessages(app, 'cs')
1645
1976
  },
1646
1977
  en: {
1978
+ [namespace]: createAppLocaleMessages(app, 'en'),
1647
1979
  translation: createAppLocaleMessages(app, 'en')
1648
1980
  }
1649
1981
  };
1650
1982
  return `import { defineRuntimeConfig } from '@modern-js/runtime';
1651
1983
  import { createInstance } from 'i18next';
1984
+ import { ultramodernRouteNamespace } from './routes/ultramodern-route-metadata';
1652
1985
 
1653
1986
  const i18nInstance = createInstance();
1654
1987
 
@@ -1656,12 +1989,12 @@ export default defineRuntimeConfig({
1656
1989
  i18n: {
1657
1990
  i18nInstance,
1658
1991
  initOptions: {
1659
- defaultNS: 'translation',
1992
+ defaultNS: ultramodernRouteNamespace,
1660
1993
  fallbackLng: 'en',
1661
1994
  interpolation: {
1662
1995
  escapeValue: false,
1663
1996
  },
1664
- ns: ['translation'],
1997
+ ns: [ultramodernRouteNamespace, 'translation'],
1665
1998
  resources: ${JSON.stringify(resources, null, 8).split('\n').join('\n ')},
1666
1999
  supportedLngs: ['en', 'cs'],
1667
2000
  },
@@ -1672,10 +2005,16 @@ export default defineRuntimeConfig({
1672
2005
  });
1673
2006
  `;
1674
2007
  }
1675
- function createAppStyles(enableTailwind) {
1676
- return `${enableTailwind ? "@import 'tailwindcss';\n\n" : ''}:root {
1677
- color: #10231c;
1678
- background: #f1eadc;
2008
+ function createCssTokenImport(scope) {
2009
+ return `@import '${ultramodern_workspace_packageName(scope, 'shared-design-tokens')}/tokens.css';\n`;
2010
+ }
2011
+ function createShellStyles(enableTailwind, scope) {
2012
+ return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
2013
+
2014
+ @layer ultramodern-shell-base {
2015
+ :root {
2016
+ color: var(--um-color-foreground);
2017
+ background: var(--um-color-canvas);
1679
2018
  font-family:
1680
2019
  Geist,
1681
2020
  Inter,
@@ -1703,9 +2042,52 @@ nav {
1703
2042
  }
1704
2043
 
1705
2044
  a {
1706
- color: #166b4b;
2045
+ color: var(--um-color-link);
2046
+ }
2047
+ }
2048
+
2049
+ @layer ultramodern-shell-overlay {
2050
+ .boundary-overlay {
2051
+ inset: 0;
2052
+ pointer-events: none;
2053
+ position: fixed;
2054
+ z-index: 70;
2055
+ }
2056
+
2057
+ .boundary-overlay__box {
2058
+ border: 0.0625rem solid var(--boundary-color);
2059
+ border-radius: 0.55rem;
2060
+ box-shadow:
2061
+ 0 0 0 0.0625rem rgba(255, 255, 255, 0.72),
2062
+ 0 0.35rem 1.25rem color-mix(in srgb, var(--boundary-color) 20%, transparent);
2063
+ position: fixed;
2064
+ }
2065
+
2066
+ .boundary-overlay__label {
2067
+ background: color-mix(in srgb, var(--boundary-color) 88%, white);
2068
+ border-radius: 999px;
2069
+ color: #0b0a08;
2070
+ font-size: 0.7rem;
2071
+ font-weight: 850;
2072
+ line-height: 1;
2073
+ padding: 0.3rem 0.55rem;
2074
+ position: absolute;
2075
+ right: 0.35rem;
2076
+ top: 0.35rem;
2077
+ white-space: nowrap;
1707
2078
  }
1708
2079
 
2080
+ .boundary-overlay__box[data-label-placement="above"] .boundary-overlay__label {
2081
+ bottom: calc(100% + 0.25rem);
2082
+ top: auto;
2083
+ }
2084
+ }
2085
+ `;
2086
+ }
2087
+ function createRemoteStyles(enableTailwind, scope, app) {
2088
+ if ('commerce' === app.domain) return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
2089
+
2090
+ @layer ultramodern-remote-${app.domain} {
1709
2091
  .commerce-shell {
1710
2092
  background: #f1eadc;
1711
2093
  color: #0b0a08;
@@ -1933,41 +2315,6 @@ a {
1933
2315
  width: 1rem;
1934
2316
  }
1935
2317
 
1936
- .boundary-overlay {
1937
- inset: 0;
1938
- pointer-events: none;
1939
- position: fixed;
1940
- z-index: 70;
1941
- }
1942
-
1943
- .boundary-overlay__box {
1944
- border: 0.0625rem solid var(--boundary-color);
1945
- border-radius: 0.55rem;
1946
- box-shadow:
1947
- 0 0 0 0.0625rem rgba(255, 255, 255, 0.72),
1948
- 0 0.35rem 1.25rem color-mix(in srgb, var(--boundary-color) 20%, transparent);
1949
- position: fixed;
1950
- }
1951
-
1952
- .boundary-overlay__label {
1953
- background: color-mix(in srgb, var(--boundary-color) 88%, white);
1954
- border-radius: 999px;
1955
- color: #0b0a08;
1956
- font-size: 0.7rem;
1957
- font-weight: 850;
1958
- line-height: 1;
1959
- padding: 0.3rem 0.55rem;
1960
- position: absolute;
1961
- right: 0.35rem;
1962
- top: 0.35rem;
1963
- white-space: nowrap;
1964
- }
1965
-
1966
- .boundary-overlay__box[data-label-placement="above"] .boundary-overlay__label {
1967
- bottom: calc(100% + 0.25rem);
1968
- top: auto;
1969
- }
1970
-
1971
2318
  @media (max-width: 860px) {
1972
2319
  .commerce-header,
1973
2320
  .commerce-footer,
@@ -1987,8 +2334,78 @@ a {
1987
2334
  min-height: 20rem;
1988
2335
  }
1989
2336
  }
2337
+ }
2338
+ `;
2339
+ return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
2340
+
2341
+ @layer ultramodern-remote-${app.domain ?? app.id} {
2342
+ [data-app-id="${app.id}"] {
2343
+ color: var(--um-color-foreground);
2344
+ background: var(--um-color-surface);
2345
+ font-family:
2346
+ Geist,
2347
+ Inter,
2348
+ ui-sans-serif,
2349
+ system-ui,
2350
+ -apple-system,
2351
+ BlinkMacSystemFont,
2352
+ "Segoe UI",
2353
+ sans-serif;
2354
+ min-height: 100vh;
2355
+ }
2356
+
2357
+ [data-app-id="${app.id}"] main {
2358
+ min-height: 100vh;
2359
+ padding: 2rem;
2360
+ }
2361
+
2362
+ [data-app-id="${app.id}"] nav {
2363
+ display: flex;
2364
+ gap: 0.75rem;
2365
+ margin-bottom: 2rem;
2366
+ }
2367
+
2368
+ [data-app-id="${app.id}"] a {
2369
+ color: var(--um-color-link);
2370
+ }
2371
+
2372
+ [data-mf-remote="${app.id}"] {
2373
+ border: 0.0625rem solid color-mix(in srgb, var(--um-color-accent) 30%, transparent);
2374
+ border-radius: 0.5rem;
2375
+ padding: 1rem;
2376
+ }
2377
+ }
2378
+ `;
2379
+ }
2380
+ function createServiceStyles(enableTailwind, scope, service) {
2381
+ return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
2382
+
2383
+ @layer ultramodern-effect-service {
2384
+ [data-app-id="${service.id}"] {
2385
+ color: var(--um-color-foreground);
2386
+ background: var(--um-color-surface);
2387
+ font-family:
2388
+ Geist,
2389
+ Inter,
2390
+ ui-sans-serif,
2391
+ system-ui,
2392
+ -apple-system,
2393
+ BlinkMacSystemFont,
2394
+ "Segoe UI",
2395
+ sans-serif;
2396
+ min-height: 100vh;
2397
+ }
2398
+
2399
+ [data-app-id="${service.id}"] main {
2400
+ min-height: 100vh;
2401
+ padding: 2rem;
2402
+ }
2403
+ }
1990
2404
  `;
1991
2405
  }
2406
+ function createAppStyles(enableTailwind, scope, app) {
2407
+ return 'shell' === app.kind ? createShellStyles(enableTailwind, scope) : createRemoteStyles(enableTailwind, scope, app);
2408
+ }
1992
2409
  function createPostcssConfig() {
1993
2410
  return `export default {
1994
2411
  plugins: {
@@ -2010,48 +2427,168 @@ function createLocalizedHeadComponent() {
2010
2427
  const supportedLanguages = ['en', 'cs'] as const;
2011
2428
  type SupportedLanguage = (typeof supportedLanguages)[number];
2012
2429
 
2013
- const localizedPath = (language: SupportedLanguage) => \`/\${language}\`;
2430
+ const localisedUrls = ultramodernLocalisedUrls as Record<
2431
+ string,
2432
+ Record<SupportedLanguage, string>
2433
+ >;
2434
+
2435
+ const isSupportedLanguage = (value: string): value is SupportedLanguage =>
2436
+ supportedLanguages.includes(value as SupportedLanguage);
2437
+
2438
+ const normalisePath = (pathname: string) => {
2439
+ const normalised = pathname.replace(/\\/+$/u, '').replace(/\\/+/gu, '/');
2440
+ return normalised.length > 0 ? normalised : '/';
2441
+ };
2442
+
2443
+ const stripLanguagePrefix = (pathname: string) => {
2444
+ const segments = normalisePath(pathname).split('/').filter(Boolean);
2445
+ if (segments.length > 0 && isSupportedLanguage(segments[0] ?? '')) {
2446
+ segments.shift();
2447
+ }
2448
+ return \`/\${segments.join('/')}\`;
2449
+ };
2450
+
2451
+ const escapeRegExp = (value: string) =>
2452
+ value.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\$&');
2453
+
2454
+ const paramName = (segment: string) => segment.slice(1).replace(/\\?$/u, '');
2455
+
2456
+ const matchPattern = (pathname: string, pattern: string) => {
2457
+ const names: string[] = [];
2458
+ const source = normalisePath(pattern)
2459
+ .split('/')
2460
+ .filter(Boolean)
2461
+ .map(segment => {
2462
+ if (segment.startsWith(':')) {
2463
+ names.push(paramName(segment));
2464
+ return segment.endsWith('?') ? '(?:/([^/]+))?' : '/([^/]+)';
2465
+ }
2466
+ return \`/\${escapeRegExp(segment)}\`;
2467
+ })
2468
+ .join('');
2469
+ const match = new RegExp(\`^\${source || '/'}$\`).exec(normalisePath(pathname));
2470
+
2471
+ if (!match) {
2472
+ return undefined;
2473
+ }
2474
+
2475
+ return names.reduce<Record<string, string>>((params, name, index) => {
2476
+ params[name] = decodeURIComponent(match[index + 1] ?? '');
2477
+ return params;
2478
+ }, {});
2479
+ };
2480
+
2481
+ const buildPath = (pattern: string, params: Record<string, string>) => {
2482
+ const path = normalisePath(pattern)
2483
+ .split('/')
2484
+ .filter(Boolean)
2485
+ .map(segment => {
2486
+ if (!segment.startsWith(':')) {
2487
+ return segment;
2488
+ }
2489
+ const value = params[paramName(segment)];
2490
+ return value ? encodeURIComponent(value) : '';
2491
+ })
2492
+ .filter(Boolean)
2493
+ .join('/');
2494
+
2495
+ return \`/\${path}\`;
2496
+ };
2497
+
2498
+ const resolveLocalisedPath = (
2499
+ pathname: string,
2500
+ targetLanguage: SupportedLanguage,
2501
+ ) => {
2502
+ const pathWithoutLanguage = stripLanguagePrefix(pathname);
2503
+
2504
+ for (const entry of Object.values(localisedUrls)) {
2505
+ const targetPattern = entry[targetLanguage];
2506
+ if (!targetPattern) {
2507
+ continue;
2508
+ }
2509
+
2510
+ for (const language of supportedLanguages) {
2511
+ const sourcePattern = entry[language];
2512
+ const params = sourcePattern
2513
+ ? matchPattern(pathWithoutLanguage, sourcePattern)
2514
+ : undefined;
2515
+ if (params) {
2516
+ return buildPath(targetPattern, params);
2517
+ }
2518
+ }
2519
+ }
2520
+
2521
+ return pathWithoutLanguage;
2522
+ };
2523
+
2524
+ const localizedPath = (pathname: string, language: SupportedLanguage) => {
2525
+ const pathWithoutLanguage = resolveLocalisedPath(pathname, language);
2526
+ return pathWithoutLanguage === '/' ? \`/\${language}\` : \`/\${language}\${pathWithoutLanguage}\`;
2527
+ };
2014
2528
 
2015
2529
  const absoluteUrl = (pathname: string) => {
2016
2530
  const origin = ULTRAMODERN_SITE_URL.replace(/\\/+$/u, '');
2017
2531
  return \`\${origin}\${pathname}\`;
2018
2532
  };
2533
+
2534
+ const locationSuffix = (location: {
2535
+ hash?: unknown;
2536
+ search?: unknown;
2537
+ searchStr?: unknown;
2538
+ }) => {
2539
+ const locationSearch =
2540
+ typeof location.searchStr === 'string'
2541
+ ? location.searchStr
2542
+ : typeof location.search === 'string'
2543
+ ? location.search
2544
+ : '';
2545
+ const locationHash = typeof location.hash === 'string' ? location.hash : '';
2546
+
2547
+ return \`\${locationSearch}\${locationHash}\`;
2548
+ };
2549
+
2019
2550
  const LocalizedHead = () => {
2020
- const canonicalPath = localizedPath(fallbackLanguage);
2551
+ const location = useLocation();
2552
+ const canonicalPath = localizedPath(location.pathname, fallbackLanguage);
2021
2553
 
2022
2554
  return (
2023
- <>
2555
+ <Helmet>
2024
2556
  <link rel="canonical" href={absoluteUrl(canonicalPath)} />
2025
2557
  {supportedLanguages.map(code => (
2026
2558
  <link
2027
- href={absoluteUrl(localizedPath(code))}
2559
+ href={absoluteUrl(localizedPath(location.pathname, code))}
2028
2560
  hrefLang={code}
2029
2561
  key={code}
2030
2562
  rel="alternate"
2031
2563
  />
2032
2564
  ))}
2033
2565
  <link
2034
- href={absoluteUrl(localizedPath(fallbackLanguage))}
2566
+ href={absoluteUrl(localizedPath(location.pathname, fallbackLanguage))}
2035
2567
  hrefLang="x-default"
2036
2568
  rel="alternate"
2037
2569
  />
2038
- </>
2570
+ </Helmet>
2039
2571
  );
2040
2572
  };
2041
2573
  `;
2042
2574
  }
2043
2575
  function createShellPage() {
2044
2576
  return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2577
+ import { Helmet } from '@modern-js/runtime/head';
2578
+ import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2579
+ import { ultramodernLocalisedUrls } from '../ultramodern-route-metadata';
2045
2580
  import { ultramodernUiMarker } from '../../ultramodern-build';
2046
2581
 
2047
2582
  const languageCodes = ['en', 'cs'] as const;
2048
2583
 
2049
- const remoteKeys = ['commerce', 'identity', 'designSystem'] as const;
2584
+ const remoteKeys = ['explore', 'decide', 'checkout'] as const;
2050
2585
 
2051
2586
  ${createLocalizedHeadComponent()}
2052
2587
  export default function ShellHome() {
2053
2588
  const { i18nInstance, language } = useModernI18n();
2054
2589
  const t = i18nInstance.t.bind(i18nInstance);
2590
+ const location = useLocation();
2591
+ const suffix = locationSuffix(location);
2055
2592
 
2056
2593
  return (
2057
2594
  <main>
@@ -2060,7 +2597,7 @@ export default function ShellHome() {
2060
2597
  {languageCodes.map(code => (
2061
2598
  <a
2062
2599
  aria-current={language === code ? 'page' : undefined}
2063
- href={\`/\${code}\`}
2600
+ href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
2064
2601
  key={code}
2065
2602
  >
2066
2603
  {t(\`shell.language.\${code}\`)}
@@ -2085,9 +2622,12 @@ export default function ShellHome() {
2085
2622
  function createRemotePage(app) {
2086
2623
  if ('remote-commerce' === app.id) return createCommerceRemotePage(app);
2087
2624
  const effectBffImport = appHasEffectApi(app) ? `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2625
+ import { Helmet } from '@modern-js/runtime/head';
2626
+ import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2088
2627
  import { useEffect, useState } from 'react';
2628
+ import { ultramodernLocalisedUrls } from '../ultramodern-route-metadata';
2089
2629
  import { ultramodernUiMarker } from '../../ultramodern-build';
2090
- ` : "import { useModernI18n } from '@modern-js/plugin-i18n/runtime';\nimport { ultramodernUiMarker } from '../../ultramodern-build';\n";
2630
+ ` : "import { useModernI18n } from '@modern-js/plugin-i18n/runtime';\nimport { Helmet } from '@modern-js/runtime/head';\nimport { useLocation } from '@modern-js/plugin-tanstack/runtime';\nimport { ultramodernLocalisedUrls } from '../ultramodern-route-metadata';\nimport { ultramodernUiMarker } from '../../ultramodern-build';\n";
2091
2631
  const effectBffState = appHasEffectApi(app) ? ` const [effectApiStatus, setEffectApiStatus] = useState('pending');
2092
2632
 
2093
2633
  useEffect(() => {
@@ -2119,6 +2659,8 @@ ${createLocalizedHeadComponent()}
2119
2659
  export default function ${toPascalCase(app.id)}Home() {
2120
2660
  const { i18nInstance, language } = useModernI18n();
2121
2661
  const t = i18nInstance.t.bind(i18nInstance);
2662
+ const location = useLocation();
2663
+ const suffix = locationSuffix(location);
2122
2664
  ${effectBffState} return (
2123
2665
  <main>
2124
2666
  <LocalizedHead />
@@ -2126,7 +2668,7 @@ ${effectBffState} return (
2126
2668
  {supportedLanguages.map(code => (
2127
2669
  <a
2128
2670
  aria-current={language === code ? 'page' : undefined}
2129
- href={\`/\${code}\`}
2671
+ href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
2130
2672
  key={code}
2131
2673
  >
2132
2674
  {t(\`${app.domain}.language.\${code}\`)}
@@ -2145,7 +2687,10 @@ ${effectBffMarkup} </main>
2145
2687
  }
2146
2688
  function createCommerceRemotePage(app) {
2147
2689
  return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2690
+ import { Helmet } from '@modern-js/runtime/head';
2691
+ import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2148
2692
  import { useEffect, useState, type CSSProperties } from 'react';
2693
+ import { ultramodernLocalisedUrls } from '../ultramodern-route-metadata';
2149
2694
  import { ultramodernUiMarker } from '../../ultramodern-build';
2150
2695
 
2151
2696
  const languageCodes = ['en', 'cs'] as const;
@@ -2318,6 +2863,8 @@ function BoundaryOverlay({
2318
2863
  export default function ${toPascalCase(app.id)}Home() {
2319
2864
  const { i18nInstance, language } = useModernI18n();
2320
2865
  const t = i18nInstance.t.bind(i18nInstance);
2866
+ const location = useLocation();
2867
+ const suffix = locationSuffix(location);
2321
2868
  const [cart, setCart] = useState<CartState>({});
2322
2869
  const [showBoundaries, setShowBoundaries] = useState(false);
2323
2870
  const [effectApiStatus, setEffectApiStatus] = useState('pending');
@@ -2409,7 +2956,7 @@ export default function ${toPascalCase(app.id)}Home() {
2409
2956
  <a
2410
2957
  aria-current={language === code ? 'page' : undefined}
2411
2958
  className="commerce-pill"
2412
- href={\`/\${code}\`}
2959
+ href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
2413
2960
  key={code}
2414
2961
  >
2415
2962
  {t(\`commerce.language.\${code}\`)}
@@ -2550,10 +3097,21 @@ export default function Layout() {
2550
3097
  `;
2551
3098
  }
2552
3099
  function createRemoteEntry(app) {
2553
- return `export { default } from './components/${remoteWidgetFile(app)}';
3100
+ if (app.exposes?.['./ProductPage']) return `export { default } from './components/product-page';
2554
3101
  `;
2555
- }
2556
- function createRemoteWidget(app) {
3102
+ if (app.exposes?.['./CartPage']) return `export { default } from './components/cart-page';
3103
+ `;
3104
+ return `export default function ${toPascalCase(app.domain ?? app.id)}Route() {
3105
+ return (
3106
+ <section data-mf-remote="${app.id}" data-mf-expose="./Route">
3107
+ <h2>${app.displayName}</h2>
3108
+ <p>Route surface for ${app.domain ?? app.id}.</p>
3109
+ </section>
3110
+ );
3111
+ }
3112
+ `;
3113
+ }
3114
+ function createRemoteWidget(app) {
2557
3115
  const componentName = `${toPascalCase(app.domain ?? app.id)}Widget`;
2558
3116
  const body = 'vertical' === app.kind ? `Owns the ${app.domain} vertical route surface.` : 'Provides shared UI primitives for the workspace.';
2559
3117
  return `export default function ${componentName}() {
@@ -2566,16 +3124,57 @@ function createRemoteWidget(app) {
2566
3124
  }
2567
3125
  `;
2568
3126
  }
3127
+ function createRemoteExposeComponent(app, expose) {
3128
+ if ('./Widget' === expose) return createRemoteWidget(app);
3129
+ const componentName = `${toPascalCase(app.domain ?? app.id)}${toPascalCase(expose.replace(/^\.\//u, ''))}`;
3130
+ if ('remote-decide' === app.id && './ProductPage' === expose) return `import AddToCart from 'checkout/AddToCart';
3131
+ import Recommendations from 'explore/Recommendations';
3132
+
3133
+ export default function ${componentName}() {
3134
+ return (
3135
+ <section data-mf-remote="${app.id}" data-mf-expose="${expose}">
3136
+ <p>Decide owns tractor product selection.</p>
3137
+ <h2>Field Loader 112</h2>
3138
+ <p>Hydraulic-ready compact tractor with guided implement matching.</p>
3139
+ <AddToCart />
3140
+ <Recommendations />
3141
+ </section>
3142
+ );
3143
+ }
3144
+ `;
3145
+ return `export default function ${componentName}() {
3146
+ return (
3147
+ <section data-mf-remote="${app.id}" data-mf-expose="${expose}">
3148
+ <h2>${app.displayName} ${expose.replace(/^\.\//u, '')}</h2>
3149
+ <p>Module Federation surface owned by ${app.ownership.team}.</p>
3150
+ </section>
3151
+ );
3152
+ }
3153
+ `;
3154
+ }
3155
+ function remoteComponentOutputPath(app, expose) {
3156
+ const exposePath = app.exposes?.[expose];
3157
+ if (!exposePath?.startsWith('./src/components/')) return;
3158
+ return `${app.directory}/${exposePath.replace(/^\.\//u, '')}`;
3159
+ }
2569
3160
  function createAppLocaleMessages(app, language) {
2570
3161
  const czechLabels = {
2571
- commerce: {
2572
- role: 'obchod',
2573
- title: 'Obchodní remote'
3162
+ checkout: {
3163
+ role: 'pokladna',
3164
+ title: 'Pokladní remote'
3165
+ },
3166
+ decide: {
3167
+ role: 'rozhodování',
3168
+ title: 'Rozhodovací remote'
2574
3169
  },
2575
3170
  'design-system': {
2576
3171
  role: 'design system',
2577
3172
  title: 'Design system remote'
2578
3173
  },
3174
+ explore: {
3175
+ role: 'procházení',
3176
+ title: 'Průzkumný remote'
3177
+ },
2579
3178
  identity: {
2580
3179
  role: 'identita',
2581
3180
  title: 'Identitní remote'
@@ -2589,9 +3188,12 @@ function createAppLocaleMessages(app, language) {
2589
3188
  switcher: 'en' === language ? 'Language' : 'Jazyk'
2590
3189
  },
2591
3190
  remotes: {
2592
- commerce: 'en' === language ? 'Commerce Remote' : 'Obchodní remote',
2593
- designSystem: 'en' === language ? 'Design System Remote' : 'Design system remote',
2594
- identity: 'en' === language ? 'Identity Remote' : 'Identitní remote'
3191
+ checkout: 'en' === language ? 'Checkout Remote' : 'Checkout remote',
3192
+ decide: 'en' === language ? 'Decide Remote' : 'Decide remote',
3193
+ explore: 'en' === language ? 'Explore Remote' : 'Explore remote'
3194
+ },
3195
+ routes: {
3196
+ home: 'en' === language ? 'Home' : 'Domů'
2595
3197
  },
2596
3198
  title: 'en' === language ? 'UltraModern SuperApp Shell' : 'UltraModern SuperApp shell'
2597
3199
  }
@@ -2672,6 +3274,16 @@ function createAppLocaleMessages(app, language) {
2672
3274
  switcher: 'en' === language ? 'Language' : 'Jazyk'
2673
3275
  },
2674
3276
  role: 'en' === language ? app.domain ?? app.kind : czechLabel.role,
3277
+ routes: {
3278
+ cart: 'en' === language ? 'Cart' : 'Košík',
3279
+ checkout: 'en' === language ? 'Checkout' : 'Pokladna',
3280
+ home: 'en' === language ? 'Home' : 'Domů',
3281
+ listing: 'en' === language ? 'Tractors' : 'Traktory',
3282
+ productDetail: 'en' === language ? 'Tractor detail' : 'Detail traktoru',
3283
+ storePicker: 'en' === language ? 'Store picker' : 'Výběr prodejce',
3284
+ thankYou: 'en' === language ? 'Order confirmation' : 'Potvrzení objednávky',
3285
+ unavailable: 'en' === language ? 'Unavailable' : 'Nedostupné'
3286
+ },
2675
3287
  title: 'en' === language ? app.displayName : czechLabel.title
2676
3288
  }
2677
3289
  };
@@ -2706,6 +3318,18 @@ function createDesignTokens() {
2706
3318
  } as const;
2707
3319
  `;
2708
3320
  }
3321
+ function createSharedDesignTokensCss() {
3322
+ return `@layer ultramodern-shared-tokens {
3323
+ :root {
3324
+ --um-color-accent: #2f8f68;
3325
+ --um-color-canvas: #f1eadc;
3326
+ --um-color-foreground: #133225;
3327
+ --um-color-link: #166b4b;
3328
+ --um-color-surface: #f6fbf7;
3329
+ }
3330
+ }
3331
+ `;
3332
+ }
2709
3333
  function serviceEffectApiExport(service = effectService) {
2710
3334
  return `${toCamelCase(effectApiStem(service))}EffectApi`;
2711
3335
  }
@@ -2718,6 +3342,12 @@ function serviceEffectApiName(service = effectService) {
2718
3342
  function serviceEffectSchemaExport(service = effectService) {
2719
3343
  return `${toCamelCase(effectApiStem(service))}ItemSchema`;
2720
3344
  }
3345
+ function serviceEffectMarkerSchemaExport(service = effectService) {
3346
+ return `${toCamelCase(effectApiStem(service))}MarkerSchema`;
3347
+ }
3348
+ function serviceEffectReadinessSchemaExport(service = effectService) {
3349
+ return `${toCamelCase(effectApiStem(service))}ReadinessSchema`;
3350
+ }
2721
3351
  function serviceEffectErrorStem(service = effectService) {
2722
3352
  const stem = effectApiStem(service);
2723
3353
  return 'recommendations' === stem ? 'recommendation' : stem;
@@ -2743,6 +3373,8 @@ function createEffectSharedApiImports() {
2743
3373
  }
2744
3374
  function createEffectSharedApiContract(service = effectService) {
2745
3375
  const schemaExport = serviceEffectSchemaExport(service);
3376
+ const markerSchemaExport = serviceEffectMarkerSchemaExport(service);
3377
+ const readinessSchemaExport = serviceEffectReadinessSchemaExport(service);
2746
3378
  const createPayloadSchemaExport = serviceEffectCreatePayloadSchemaExport(service);
2747
3379
  const notFoundErrorExport = serviceEffectNotFoundErrorExport(service);
2748
3380
  const notFoundSchemaExport = serviceEffectNotFoundSchemaExport(service);
@@ -2751,19 +3383,33 @@ function createEffectSharedApiContract(service = effectService) {
2751
3383
  const groupName = serviceEffectGroupName(service);
2752
3384
  const stem = effectApiStem(service);
2753
3385
  const servicePrefix = effectApiPrefix(service);
2754
- return `export const ${schemaExport} = Schema.Struct({
3386
+ return `export const ${markerSchemaExport} = Schema.Struct({
3387
+ appId: Schema.String,
3388
+ packageName: Schema.String,
3389
+ version: Schema.String,
3390
+ build: Schema.String,
3391
+ deployProfile: Schema.String,
3392
+ surface: Schema.String,
3393
+ });
3394
+
3395
+ export const ${schemaExport} = Schema.Struct({
2755
3396
  id: Schema.String,
2756
- marker: Schema.Struct({
2757
- appId: Schema.String,
2758
- packageName: Schema.String,
2759
- version: Schema.String,
2760
- build: Schema.String,
2761
- deployProfile: Schema.String,
2762
- surface: Schema.String,
2763
- }),
3397
+ marker: ${markerSchemaExport},
2764
3398
  title: Schema.String,
2765
3399
  });
2766
3400
 
3401
+ export const ${readinessSchemaExport} = Schema.Struct({
3402
+ checks: Schema.Struct({
3403
+ effectBff: Schema.Literal('ready'),
3404
+ moduleFederation: Schema.Literal('ready'),
3405
+ ssr: Schema.Literal('ready'),
3406
+ translations: Schema.Literal('ready'),
3407
+ }),
3408
+ marker: ${markerSchemaExport},
3409
+ status: Schema.Literal('ready'),
3410
+ versionSkew: Schema.Literal('none'),
3411
+ });
3412
+
2767
3413
  export const ${createPayloadSchemaExport} = Schema.Struct({
2768
3414
  title: Schema.String,
2769
3415
  });
@@ -2799,6 +3445,11 @@ export const ${apiExport} = HttpApi.make('${apiName}').add(
2799
3445
  }),
2800
3446
  }),
2801
3447
  )
3448
+ .add(
3449
+ HttpApiEndpoint.get('readiness', '/effect/${stem}/readiness', {
3450
+ success: ${readinessSchemaExport},
3451
+ }),
3452
+ )
2802
3453
  .add(
2803
3454
  HttpApiEndpoint.get('get', '/effect/${stem}/:id', {
2804
3455
  params: {
@@ -2825,6 +3476,12 @@ export const ${groupName}OperationContexts = {
2825
3476
  method: 'GET',
2826
3477
  source: 'generated-client',
2827
3478
  },
3479
+ readiness: {
3480
+ operationId: '${apiName}:${groupName}:readiness',
3481
+ routePath: '/effect/${stem}/readiness',
3482
+ method: 'GET',
3483
+ source: 'generated-client',
3484
+ },
2828
3485
  get: {
2829
3486
  operationId: '${apiName}:${groupName}:get',
2830
3487
  routePath: '/effect/${stem}/:id',
@@ -2843,6 +3500,7 @@ export const ${groupName}ApiContract = {
2843
3500
  basePath: '${servicePrefix}/effect/${stem}',
2844
3501
  ownerId: '${service.id}',
2845
3502
  servicePrefix: '${servicePrefix}',
3503
+ readinessPath: '${servicePrefix}/effect/${stem}/readiness',
2846
3504
  } as const;
2847
3505
  `;
2848
3506
  }
@@ -2911,6 +3569,24 @@ const ${groupName}Layer = HttpApiBuilder.group(
2911
3569
  }),
2912
3570
  ),
2913
3571
  )
3572
+ .handle('readiness', () =>
3573
+ Effect.succeed({
3574
+ checks: {
3575
+ effectBff: 'ready' as const,
3576
+ moduleFederation: 'ready' as const,
3577
+ ssr: 'ready' as const,
3578
+ translations: 'ready' as const,
3579
+ },
3580
+ marker: ultramodernApiMarker,
3581
+ status: 'ready' as const,
3582
+ versionSkew: 'none' as const,
3583
+ }).pipe(
3584
+ Effect.withSpan('ultramodern.effect.${groupName}.readiness', {
3585
+ attributes: operationAttributes(${groupName}OperationContexts.readiness),
3586
+ kind: 'server',
3587
+ }),
3588
+ ),
3589
+ )
2914
3590
  .handle('get', ({ params }) => {
2915
3591
  const item = ${groupName}Items.find(item => item.id === params.id);
2916
3592
  return (item !== undefined
@@ -2960,6 +3636,7 @@ function createEffectClient(service, contractImportPath) {
2960
3636
  const clientOptionsName = `${toPascalCase(stem)}ClientOptions`;
2961
3637
  const createClientName = `create${toPascalCase(stem)}Client`;
2962
3638
  const listName = `list${toPascalCase(stem)}`;
3639
+ const readinessName = `get${toPascalCase(stem)}Readiness`;
2963
3640
  const getName = `get${toPascalCase(singular)}`;
2964
3641
  const createName = `create${toPascalCase(singular)}`;
2965
3642
  return `import {
@@ -3004,6 +3681,20 @@ export function ${listName}(
3004
3681
  );
3005
3682
  }
3006
3683
 
3684
+ export function ${readinessName}(
3685
+ options: ${clientOptionsName} = {},
3686
+ ) {
3687
+ return runEffectRequest(
3688
+ ${createClientName}({
3689
+ ...options,
3690
+ operationContext:
3691
+ options.operationContext ?? ${groupName}OperationContexts.readiness,
3692
+ }),
3693
+ ).then(client =>
3694
+ runEffectRequest(client.${groupName}.readiness({})),
3695
+ );
3696
+ }
3697
+
3007
3698
  export function ${getName}(
3008
3699
  id: string,
3009
3700
  options: ${clientOptionsName} = {},
@@ -3039,17 +3730,141 @@ export function ${createName}(
3039
3730
  }
3040
3731
  function createShellEffectClient(scope) {
3041
3732
  return `export {
3042
- createRecommendation,
3043
- createRecommendationsClient,
3044
- getRecommendation,
3045
- listRecommendations,
3046
- type RecommendationsClientOptions,
3047
- } from '${ultramodern_workspace_packageName(scope, 'remote-commerce')}/effect/client';
3733
+ createCheckout,
3734
+ createCheckoutClient,
3735
+ getCheckout,
3736
+ getCheckoutReadiness,
3737
+ listCheckout,
3738
+ type CheckoutClientOptions,
3739
+ } from '${ultramodern_workspace_packageName(scope, 'remote-checkout')}/effect/client';
3740
+
3741
+ export {
3742
+ createDecide,
3743
+ createDecideClient,
3744
+ getDecide,
3745
+ getDecideReadiness,
3746
+ listDecide,
3747
+ type DecideClientOptions,
3748
+ } from '${ultramodern_workspace_packageName(scope, 'remote-decide')}/effect/client';
3749
+
3750
+ export {
3751
+ createExplore,
3752
+ createExploreClient,
3753
+ getExplore,
3754
+ getExploreReadiness,
3755
+ listExplore,
3756
+ type ExploreClientOptions,
3757
+ } from '${ultramodern_workspace_packageName(scope, 'remote-explore')}/effect/client';
3048
3758
  `;
3049
3759
  }
3050
3760
  function toPascalCase(value) {
3051
3761
  return value.split(/[-_]+/).filter(Boolean).map((part)=>`${part.charAt(0).toUpperCase()}${part.slice(1)}`).join('');
3052
3762
  }
3763
+ function createEffectReadinessContract(app) {
3764
+ const stem = effectApiStem(app);
3765
+ return {
3766
+ endpoint: `/effect/${stem}/readiness`,
3767
+ marker: {
3768
+ ui: 'ultramodernUiMarker',
3769
+ api: 'ultramodernApiMarker',
3770
+ skew: 'none'
3771
+ },
3772
+ checks: [
3773
+ 'moduleFederation',
3774
+ 'ssr',
3775
+ 'translations',
3776
+ 'effectBff'
3777
+ ]
3778
+ };
3779
+ }
3780
+ function createEffectRequestContextContract() {
3781
+ return {
3782
+ propagatedHeaders: [
3783
+ 'accept-language',
3784
+ 'authorization',
3785
+ 'traceparent',
3786
+ 'x-correlation-id',
3787
+ 'x-tenant-id',
3788
+ 'x-ultramodern-env',
3789
+ 'x-vertical-version-id'
3790
+ ],
3791
+ source: 'shell-to-vertical-effect-client'
3792
+ };
3793
+ }
3794
+ function createEffectDomainOperations(app) {
3795
+ const stem = effectApiStem(app);
3796
+ const group = serviceEffectGroupName(app);
3797
+ const basePath = `/effect/${stem}`;
3798
+ if ('checkout' === stem) return {
3799
+ cartSnapshot: {
3800
+ client: 'listCheckout',
3801
+ method: 'GET',
3802
+ path: basePath,
3803
+ resource: 'cart',
3804
+ owner: app.id
3805
+ },
3806
+ cartMutation: {
3807
+ client: 'createCheckout',
3808
+ method: 'POST',
3809
+ path: basePath,
3810
+ resource: 'cart-line',
3811
+ owner: app.id
3812
+ },
3813
+ orderConfirmation: {
3814
+ client: 'getCheckout',
3815
+ method: 'GET',
3816
+ path: `${basePath}/:id`,
3817
+ resource: 'order',
3818
+ owner: app.id
3819
+ }
3820
+ };
3821
+ if ('decide' === stem) return {
3822
+ productDetail: {
3823
+ client: 'getDecide',
3824
+ method: 'GET',
3825
+ path: `${basePath}/:id`,
3826
+ resource: 'product-detail',
3827
+ owner: app.id
3828
+ },
3829
+ configurationDraft: {
3830
+ client: 'createDecide',
3831
+ method: 'POST',
3832
+ path: basePath,
3833
+ resource: 'configuration',
3834
+ owner: app.id
3835
+ },
3836
+ productList: {
3837
+ client: 'listDecide',
3838
+ method: 'GET',
3839
+ path: basePath,
3840
+ resource: 'products',
3841
+ owner: app.id
3842
+ }
3843
+ };
3844
+ return {
3845
+ recommendationFeed: {
3846
+ client: `list${toPascalCase(stem)}`,
3847
+ method: 'GET',
3848
+ path: basePath,
3849
+ resource: 'recommendations',
3850
+ owner: app.id
3851
+ },
3852
+ recommendationDetail: {
3853
+ client: `get${toPascalCase(serviceEffectErrorStem(app))}`,
3854
+ method: 'GET',
3855
+ path: `${basePath}/:id`,
3856
+ resource: 'recommendation',
3857
+ owner: app.id
3858
+ },
3859
+ recommendationCreate: {
3860
+ client: `create${toPascalCase(serviceEffectErrorStem(app))}`,
3861
+ method: 'POST',
3862
+ path: basePath,
3863
+ resource: group,
3864
+ owner: app.id
3865
+ }
3866
+ };
3867
+ }
3053
3868
  function effectApiTopologyMetadata(app) {
3054
3869
  if (!appHasEffectApi(app)) return;
3055
3870
  return {
@@ -3069,7 +3884,10 @@ function effectApiTopologyMetadata(app) {
3069
3884
  },
3070
3885
  serverEntry: `${app.directory}/api/effect/index.ts`,
3071
3886
  basePath: `${app.effectApi.prefix}/effect/${app.effectApi.stem}`,
3072
- consumedBy: app.effectApi.consumedBy
3887
+ consumedBy: app.effectApi.consumedBy,
3888
+ readiness: createEffectReadinessContract(app),
3889
+ requestContext: createEffectRequestContextContract(),
3890
+ domainOperations: createEffectDomainOperations(app)
3073
3891
  }
3074
3892
  };
3075
3893
  }
@@ -3088,14 +3906,11 @@ function createTopology(scope) {
3088
3906
  moduleFederation: {
3089
3907
  role: 'host',
3090
3908
  name: shellApp.mfName,
3091
- remotes: remoteApps.map((remote)=>({
3092
- id: remote.id,
3093
- name: remote.mfName,
3094
- manifestUrl: `http://localhost:${remote.port}/mf-manifest.json`
3095
- })),
3909
+ remotes: createModuleFederationRemoteContracts(shellApp),
3096
3910
  ssr: true,
3097
3911
  sharedContractVersion: 'mf-ssr-contract-v1'
3098
3912
  },
3913
+ cloudflare: createCloudflareDeployContract(scope, shellApp),
3099
3914
  ownership: shellApp.ownership
3100
3915
  },
3101
3916
  remotes: remoteApps.map((remote)=>({
@@ -3108,6 +3923,10 @@ function createTopology(scope) {
3108
3923
  name: remote.mfName,
3109
3924
  manifestUrl: `http://localhost:${remote.port}/mf-manifest.json`,
3110
3925
  exposes: Object.keys(remote.exposes ?? {}),
3926
+ ...remote.remoteRefs?.length ? {
3927
+ remoteRefs: remote.remoteRefs,
3928
+ remotes: createModuleFederationRemoteContracts(remote)
3929
+ } : {},
3111
3930
  ssr: true,
3112
3931
  fallbackTelemetryEvent: 'modernjs:mv-runtime-parity',
3113
3932
  sharedContractVersion: 'mf-ssr-contract-v1'
@@ -3115,6 +3934,7 @@ function createTopology(scope) {
3115
3934
  ...effectApiTopologyMetadata(remote) ? {
3116
3935
  api: effectApiTopologyMetadata(remote)
3117
3936
  } : {},
3937
+ cloudflare: createCloudflareDeployContract(scope, remote),
3118
3938
  ownership: remote.ownership
3119
3939
  })),
3120
3940
  effectServices: [],
@@ -3225,6 +4045,11 @@ function createEffectOperationContract(target) {
3225
4045
  path: `/effect/${stem}`,
3226
4046
  source: 'generated-client'
3227
4047
  },
4048
+ readiness: {
4049
+ method: 'GET',
4050
+ path: `/effect/${stem}/readiness`,
4051
+ source: 'generated-client'
4052
+ },
3228
4053
  get: {
3229
4054
  method: 'GET',
3230
4055
  path: `/effect/${stem}/:id`,
@@ -3281,7 +4106,143 @@ function createAppConfigContract(app) {
3281
4106
  } : {}
3282
4107
  };
3283
4108
  }
3284
- function createStylingContract(enableTailwind) {
4109
+ function cssLayerName(app) {
4110
+ if ('shell' === app.kind) return 'ultramodern-shell-base';
4111
+ return `ultramodern-remote-${app.domain ?? app.id}`;
4112
+ }
4113
+ function cssRole(app) {
4114
+ if ('shell' === app.kind) return 'shell-base-overlay';
4115
+ return 'horizontal-remote' === app.kind ? 'horizontal-remote-css' : 'vertical-remote-css';
4116
+ }
4117
+ function cssClassPrefix(app) {
4118
+ if ('shell' === app.kind) return 'shell-';
4119
+ return `${app.domain ?? app.id.replace(/^remote-/, '')}-`;
4120
+ }
4121
+ function createCssDedupeContract(scope) {
4122
+ return {
4123
+ strategy: 'shared-token-package-plus-css-content-hash',
4124
+ sharedPackage: ultramodern_workspace_packageName(scope, 'shared-design-tokens'),
4125
+ sharedLayers: [
4126
+ 'ultramodern-shared-tokens'
4127
+ ],
4128
+ runtimeLoad: 'once-per-content-hash',
4129
+ duplicateBaseStylesAllowed: false
4130
+ };
4131
+ }
4132
+ function createCssSsrContract(app) {
4133
+ return {
4134
+ cloudflare: true,
4135
+ firstPaintRequired: true,
4136
+ linkEmission: 'modern-ssr-css-assets',
4137
+ remoteCss: 'shell' === app.kind ? 'host-preloads-shell-and-shared-css' : 'remote-manifest-owned-css'
4138
+ };
4139
+ }
4140
+ function createAppCssFederationContract(scope, app) {
4141
+ const ownedLayers = 'shell' === app.kind ? [
4142
+ 'ultramodern-shell-base',
4143
+ 'ultramodern-shell-overlay'
4144
+ ] : [
4145
+ cssLayerName(app)
4146
+ ];
4147
+ return {
4148
+ owner: {
4149
+ id: app.id,
4150
+ package: ultramodern_workspace_packageName(scope, app.packageSuffix),
4151
+ team: app.ownership.team
4152
+ },
4153
+ role: cssRole(app),
4154
+ rootSelector: `[data-app-id="${app.id}"]`,
4155
+ classPrefix: cssClassPrefix(app),
4156
+ layers: {
4157
+ shared: [
4158
+ 'ultramodern-shared-tokens'
4159
+ ],
4160
+ owned: ownedLayers,
4161
+ imports: 'shell' === app.kind ? [
4162
+ 'ultramodern-shared-tokens'
4163
+ ] : [
4164
+ 'ultramodern-shared-tokens'
4165
+ ]
4166
+ },
4167
+ entrypoints: {
4168
+ layoutImport: 'src/routes/layout.tsx',
4169
+ css: [
4170
+ 'src/routes/index.css'
4171
+ ],
4172
+ ...'shell' !== app.kind ? {
4173
+ remoteEntry: 'src/remote-entry.tsx'
4174
+ } : {}
4175
+ },
4176
+ assets: {
4177
+ shared: [
4178
+ `${ultramodern_workspace_packageName(scope, 'shared-design-tokens')}/tokens.css`
4179
+ ],
4180
+ owned: [
4181
+ 'src/routes/index.css'
4182
+ ],
4183
+ emittedBy: 'modern-rspack-css-extraction',
4184
+ contentHash: true
4185
+ },
4186
+ dedupe: createCssDedupeContract(scope),
4187
+ ssr: createCssSsrContract(app)
4188
+ };
4189
+ }
4190
+ function createCssFederationContract(scope) {
4191
+ return {
4192
+ schemaVersion: 1,
4193
+ sharedDesignTokens: {
4194
+ owner: {
4195
+ id: 'shared-design-tokens',
4196
+ package: ultramodern_workspace_packageName(scope, 'shared-design-tokens'),
4197
+ team: 'super-app-platform'
4198
+ },
4199
+ role: 'shared-design-tokens',
4200
+ rootSelector: ':root',
4201
+ classPrefix: '--um-',
4202
+ layers: {
4203
+ owned: [
4204
+ 'ultramodern-shared-tokens'
4205
+ ]
4206
+ },
4207
+ entrypoints: {
4208
+ css: [
4209
+ 'packages/shared-design-tokens/src/tokens.css'
4210
+ ],
4211
+ typescript: [
4212
+ 'packages/shared-design-tokens/src/index.ts'
4213
+ ]
4214
+ },
4215
+ assets: {
4216
+ exports: [
4217
+ './tokens.css'
4218
+ ],
4219
+ css: [
4220
+ 'packages/shared-design-tokens/src/tokens.css'
4221
+ ]
4222
+ },
4223
+ dedupe: createCssDedupeContract(scope),
4224
+ ssr: {
4225
+ cloudflare: true,
4226
+ firstPaintRequired: true,
4227
+ importedByApps: true
4228
+ }
4229
+ },
4230
+ ownershipRules: {
4231
+ shell: [
4232
+ 'base',
4233
+ 'overlay'
4234
+ ],
4235
+ remotes: [
4236
+ 'vertical-css'
4237
+ ],
4238
+ forbiddenRemoteLayers: [
4239
+ 'ultramodern-shell-base',
4240
+ 'ultramodern-shell-overlay'
4241
+ ]
4242
+ }
4243
+ };
4244
+ }
4245
+ function createStylingContract(scope, app, enableTailwind) {
3285
4246
  return {
3286
4247
  tailwind: enableTailwind,
3287
4248
  ...enableTailwind ? {
@@ -3291,21 +4252,28 @@ function createStylingContract(enableTailwind) {
3291
4252
  contentGlobs: [
3292
4253
  './src/**/*.{js,jsx,ts,tsx}'
3293
4254
  ]
3294
- } : {}
4255
+ } : {},
4256
+ federation: createAppCssFederationContract(scope, app)
3295
4257
  };
3296
4258
  }
3297
4259
  function createAppGeneratedContract(scope, app, apps, enableTailwind) {
3298
- const remoteAppsForShell = apps.filter((candidate)=>'shell' !== candidate.kind && candidate.mfName);
4260
+ const appWithResolvedRefs = 'shell' === app.kind ? {
4261
+ ...app,
4262
+ remoteRefs: apps.filter((candidate)=>'shell' !== candidate.kind).map((candidate)=>candidate.id)
4263
+ } : app;
4264
+ const consumedRemotes = createModuleFederationRemoteContracts(appWithResolvedRefs, apps);
3299
4265
  return {
3300
4266
  id: app.id,
3301
4267
  package: ultramodern_workspace_packageName(scope, app.packageSuffix),
3302
4268
  path: app.directory,
3303
4269
  kind: app.kind,
3304
4270
  config: createAppConfigContract(app),
3305
- styling: createStylingContract(enableTailwind),
4271
+ styling: createStylingContract(scope, app, enableTailwind),
3306
4272
  deploy: {
3307
4273
  target: 'cloudflare',
4274
+ cloudflare: createCloudflareDeployContract(scope, app),
3308
4275
  worker: {
4276
+ name: createCloudflareWorkerName(scope, app),
3309
4277
  ssr: true
3310
4278
  },
3311
4279
  output: {
@@ -3319,25 +4287,42 @@ function createAppGeneratedContract(scope, app, apps, enableTailwind) {
3319
4287
  },
3320
4288
  i18n: {
3321
4289
  plugin: '@modern-js/plugin-i18n',
3322
- backend: false,
4290
+ backend: {
4291
+ enabled: true,
4292
+ loadPath: '/locales/{{lng}}/{{ns}}.json'
4293
+ },
3323
4294
  reactI18next: false,
3324
4295
  languages: [
3325
4296
  'en',
3326
4297
  'cs'
3327
4298
  ],
3328
4299
  fallbackLanguage: 'en',
3329
- publicDir: './locales'
4300
+ namespace: appI18nNamespace(app),
4301
+ namespaces: [
4302
+ appI18nNamespace(app),
4303
+ 'translation'
4304
+ ],
4305
+ publicDir: './locales',
4306
+ localisedUrls: createLocalisedUrlsMap(app),
4307
+ resourceOwnership: {
4308
+ ownerAppId: app.id,
4309
+ source: 'route-owned',
4310
+ staticJson: `./locales/{lng}/${appI18nNamespace(app)}.json`
4311
+ }
4312
+ },
4313
+ routes: {
4314
+ source: 'route-owned',
4315
+ metadataExport: './src/routes/ultramodern-route-metadata',
4316
+ localisedUrls: createLocalisedUrlsMap(app),
4317
+ owned: createRouteOwnedI18nPaths(app),
4318
+ generatedRouteMap: true,
4319
+ manualOverrides: []
3330
4320
  },
3331
4321
  moduleFederation: {
3332
4322
  name: app.mfName,
3333
- ...'shell' === app.kind ? {
3334
- remotes: remoteAppsForShell.map((remote)=>({
3335
- id: remote.id,
3336
- alias: remoteDependencyAlias(remote),
3337
- name: remote.mfName,
3338
- manifestEnv: createRemoteManifestEnv(remote),
3339
- manifestUrl: `http://localhost:${remote.port}/mf-manifest.json`
3340
- }))
4323
+ ...appWithResolvedRefs.remoteRefs?.length ? {
4324
+ remoteRefs: appWithResolvedRefs.remoteRefs,
4325
+ remotes: consumedRemotes
3341
4326
  } : {},
3342
4327
  exposes: Object.keys(app.exposes ?? {}),
3343
4328
  dts: {
@@ -3409,6 +4394,9 @@ function createAppGeneratedContract(scope, app, apps, enableTailwind) {
3409
4394
  workerEntry: 'worker/__modern_bff_effect.js',
3410
4395
  contract: './shared/effect/api',
3411
4396
  client: './effect/client',
4397
+ readiness: createEffectReadinessContract(app),
4398
+ requestContext: createEffectRequestContextContract(),
4399
+ domainOperations: createEffectDomainOperations(app),
3412
4400
  ...createEffectOperationContract(app)
3413
4401
  }
3414
4402
  } : {}
@@ -3437,6 +4425,7 @@ function createGeneratedContract(scope, apps = [
3437
4425
  zephyrAgent: ZEPHYR_AGENT_VERSION,
3438
4426
  wrangler: WRANGLER_VERSION
3439
4427
  },
4428
+ cssFederation: createCssFederationContract(scope),
3440
4429
  apps: apps.map((app)=>createAppGeneratedContract(scope, app, apps, enableTailwind))
3441
4430
  };
3442
4431
  }
@@ -3559,16 +4548,653 @@ function createTemplateManifest(modernVersion, packageSource) {
3559
4548
  }
3560
4549
  };
3561
4550
  }
4551
+ function createAssertMfTypesScript(remotes = remoteApps) {
4552
+ return `import fs from 'node:fs';
4553
+ import path from 'node:path';
4554
+
4555
+ const root = process.cwd();
4556
+ const defaultAppDirs = ${JSON.stringify(remotes.map((remote)=>remote.directory), null, 2)};
4557
+
4558
+ const candidateDirs = process.argv.slice(2);
4559
+ const appDirs = candidateDirs.length
4560
+ ? candidateDirs
4561
+ : fs.existsSync(path.join(root, 'module-federation.config.ts'))
4562
+ ? ['.']
4563
+ : defaultAppDirs;
4564
+
4565
+ for (const appDir of appDirs) {
4566
+ const configPath = path.join(root, appDir, 'module-federation.config.ts');
4567
+ if (!fs.existsSync(configPath)) {
4568
+ throw new Error(
4569
+ \`Missing Module Federation config: \${path.relative(root, configPath)}\`,
4570
+ );
4571
+ }
4572
+
4573
+ const config = fs.readFileSync(configPath, 'utf-8');
4574
+ if (config.includes('dts: false')) {
4575
+ throw new Error(
4576
+ \`Module Federation DTS must stay enabled: \${path.relative(root, configPath)}\`,
4577
+ );
4578
+ }
4579
+
4580
+ if (!config.includes("compilerInstance: '--package typescript -- tsc'")) {
4581
+ throw new Error(
4582
+ \`Module Federation DTS must use the workspace TypeScript compiler: \${path.relative(root, configPath)}\`,
4583
+ );
4584
+ }
4585
+
4586
+ if (!config.includes('exposes:')) {
4587
+ continue;
4588
+ }
4589
+
4590
+ const typesArchivePath = path.join(root, appDir, 'dist/@mf-types.zip');
4591
+ if (!fs.existsSync(typesArchivePath)) {
4592
+ throw new Error(
4593
+ \`Missing Module Federation DTS archive: \${path.relative(root, typesArchivePath)}\`,
4594
+ );
4595
+ }
4596
+
4597
+ const stats = fs.statSync(typesArchivePath);
4598
+ if (stats.size === 0) {
4599
+ throw new Error(
4600
+ \`Empty Module Federation DTS archive: \${path.relative(root, typesArchivePath)}\`,
4601
+ );
4602
+ }
4603
+ }
4604
+ `;
4605
+ }
4606
+ function createWorkspaceValidationScript(scope, enableTailwind, remotes = remoteApps) {
4607
+ const verticals = remotes.filter(appHasEffectApi).map((remote)=>({
4608
+ id: remote.id,
4609
+ domain: remote.domain,
4610
+ stem: remote.effectApi.stem,
4611
+ group: serviceEffectGroupName(remote),
4612
+ path: remote.directory,
4613
+ mfName: remote.mfName,
4614
+ apiPrefix: remote.effectApi.prefix,
4615
+ packageName: ultramodern_workspace_packageName(scope, remote.packageSuffix),
4616
+ exposes: Object.keys(remote.exposes ?? {}),
4617
+ componentPaths: Object.keys(remote.exposes ?? {}).map((expose)=>remoteComponentOutputPath(remote, expose)).filter((componentPath)=>Boolean(componentPath)),
4618
+ namespace: appI18nNamespace(remote),
4619
+ routePagePaths: createRouteOwnedI18nPaths(remote).filter((route)=>'/' !== route.canonicalPath).map((route)=>createRoutePageFilePath(remote, route.canonicalPath)),
4620
+ localisedUrls: createLocalisedUrlsMap(remote),
4621
+ remoteRefs: remote.remoteRefs ?? []
4622
+ }));
4623
+ const shellNamespace = appI18nNamespace(shellApp);
4624
+ const oldRemotePaths = [
4625
+ 'apps/remotes/remote-commerce',
4626
+ 'apps/remotes/remote-identity',
4627
+ 'apps/remotes/remote-design-system'
4628
+ ];
4629
+ return `import { execFileSync } from 'node:child_process';
4630
+ import fs from 'node:fs';
4631
+ import path from 'node:path';
4632
+
4633
+ const root = process.cwd();
4634
+ const packageScope = '${scope}';
4635
+ const expectedPnpmVersion = '${PNPM_VERSION}';
4636
+ const tailwindEnabled = ${JSON.stringify(enableTailwind)};
4637
+ const fullStackVerticals = ${JSON.stringify(verticals, null, 2)};
4638
+ const shellNamespace = ${JSON.stringify(shellNamespace)};
4639
+ const oldRemotePaths = ${JSON.stringify(oldRemotePaths, null, 2)};
4640
+
4641
+ const readText = relativePath => fs.readFileSync(path.join(root, relativePath), 'utf-8');
4642
+ const readJson = relativePath => JSON.parse(readText(relativePath));
4643
+ const assert = (condition, message) => {
4644
+ if (!condition) {
4645
+ throw new Error(message);
4646
+ }
4647
+ };
4648
+ const assertExists = relativePath => {
4649
+ assert(fs.existsSync(path.join(root, relativePath)), \`Missing \${relativePath}\`);
4650
+ };
4651
+ const assertNotExists = relativePath => {
4652
+ assert(!fs.existsSync(path.join(root, relativePath)), \`Unexpected \${relativePath}\`);
4653
+ };
4654
+ const expectedWorkerName = packageSuffix => \`\${packageScope}-\${packageSuffix}\`.slice(0, 63);
4655
+
4656
+ const activePnpmVersion = execFileSync('pnpm', ['--version'], {
4657
+ cwd: root,
4658
+ encoding: 'utf-8',
4659
+ stdio: ['ignore', 'pipe', 'pipe'],
4660
+ }).trim();
4661
+
4662
+ assert(
4663
+ activePnpmVersion === expectedPnpmVersion,
4664
+ \`Generated workspace requires pnpm \${expectedPnpmVersion}; active pnpm is \${activePnpmVersion}. Run mise install, then rerun through mise exec -- pnpm ...\`,
4665
+ );
4666
+
4667
+ const requiredPaths = [
4668
+ 'AGENTS.md',
4669
+ '.gitignore',
4670
+ 'package.json',
4671
+ 'pnpm-workspace.yaml',
4672
+ 'tsconfig.base.json',
4673
+ 'oxlint.config.ts',
4674
+ 'oxfmt.config.ts',
4675
+ '.github/renovate.json',
4676
+ '.github/workflows/ultramodern-workspace-gates.yml',
4677
+ '.agents/skills-lock.json',
4678
+ '.agents/agent-reference-repos.json',
4679
+ '.agents/rstackjs-agent-skills-LICENSE',
4680
+ 'topology/reference-topology.json',
4681
+ 'topology/ownership.json',
4682
+ 'topology/local-overlays/development.json',
4683
+ '.modernjs/ultramodern-workspace-template-manifest.json',
4684
+ '.modernjs/ultramodern-package-source.json',
4685
+ '.modernjs/ultramodern-generated-contract.json',
4686
+ 'scripts/assert-mf-types.mjs',
4687
+ 'scripts/bootstrap-agent-skills.mjs',
4688
+ 'scripts/proof-cloudflare-version.mjs',
4689
+ 'scripts/setup-agent-reference-repos.mjs',
4690
+ 'apps/shell-super-app/package.json',
4691
+ 'apps/shell-super-app/modern.config.ts',
4692
+ 'apps/shell-super-app/module-federation.config.ts',
4693
+ 'apps/shell-super-app/src/modern-app-env.d.ts',
4694
+ 'apps/shell-super-app/src/modern.runtime.ts',
4695
+ 'apps/shell-super-app/src/effect/recommendations-client.ts',
4696
+ 'apps/shell-super-app/locales/en/translation.json',
4697
+ \`apps/shell-super-app/locales/en/\${shellNamespace}.json\`,
4698
+ 'apps/shell-super-app/locales/cs/translation.json',
4699
+ \`apps/shell-super-app/locales/cs/\${shellNamespace}.json\`,
4700
+ 'apps/shell-super-app/src/routes/index.css',
4701
+ 'apps/shell-super-app/src/routes/layout.tsx',
4702
+ 'apps/shell-super-app/src/routes/ultramodern-route-metadata.ts',
4703
+ 'apps/shell-super-app/src/routes/[lang]/page.tsx',
4704
+ 'packages/shared-contracts/src/index.ts',
4705
+ 'packages/shared-design-tokens/src/index.ts',
4706
+ 'packages/shared-design-tokens/src/tokens.css',
4707
+ 'packages/shared-effect-api/src/index.ts',
4708
+ ];
4709
+
4710
+ for (const vertical of fullStackVerticals) {
4711
+ requiredPaths.push(
4712
+ \`\${vertical.path}/package.json\`,
4713
+ \`\${vertical.path}/modern.config.ts\`,
4714
+ \`\${vertical.path}/module-federation.config.ts\`,
4715
+ \`\${vertical.path}/api/effect/index.ts\`,
4716
+ \`\${vertical.path}/shared/effect/api.ts\`,
4717
+ \`\${vertical.path}/src/effect/\${vertical.stem}-client.ts\`,
4718
+ \`\${vertical.path}/src/modern-app-env.d.ts\`,
4719
+ \`\${vertical.path}/src/modern.runtime.ts\`,
4720
+ \`\${vertical.path}/src/remote-entry.tsx\`,
4721
+ ...vertical.componentPaths,
4722
+ \`\${vertical.path}/locales/en/translation.json\`,
4723
+ \`\${vertical.path}/locales/en/\${vertical.namespace}.json\`,
4724
+ \`\${vertical.path}/locales/cs/translation.json\`,
4725
+ \`\${vertical.path}/locales/cs/\${vertical.namespace}.json\`,
4726
+ \`\${vertical.path}/src/routes/index.css\`,
4727
+ \`\${vertical.path}/src/routes/layout.tsx\`,
4728
+ \`\${vertical.path}/src/routes/ultramodern-route-metadata.ts\`,
4729
+ \`\${vertical.path}/src/routes/[lang]/page.tsx\`,
4730
+ ...vertical.routePagePaths,
4731
+ );
4732
+ }
4733
+
4734
+ if (tailwindEnabled) {
4735
+ requiredPaths.push(
4736
+ 'apps/shell-super-app/postcss.config.mjs',
4737
+ 'apps/shell-super-app/tailwind.config.ts',
4738
+ ...fullStackVerticals.flatMap(vertical => [
4739
+ \`\${vertical.path}/postcss.config.mjs\`,
4740
+ \`\${vertical.path}/tailwind.config.ts\`,
4741
+ ]),
4742
+ );
4743
+ }
4744
+
4745
+ for (const requiredPath of requiredPaths) {
4746
+ assertExists(requiredPath);
4747
+ }
4748
+ for (const oldRemotePath of oldRemotePaths) {
4749
+ assertNotExists(oldRemotePath);
4750
+ }
4751
+ assertNotExists('services/service-recommendations-effect');
4752
+
4753
+ const rootPackage = readJson('package.json');
4754
+ const packageSource = readJson('.modernjs/ultramodern-package-source.json');
4755
+ const generatedContract = readJson('.modernjs/ultramodern-generated-contract.json');
4756
+ const topology = readJson('topology/reference-topology.json');
4757
+ const ownership = readJson('topology/ownership.json');
4758
+ const overlay = readJson('topology/local-overlays/development.json');
4759
+
4760
+ assert(rootPackage.private === true, 'Root package must be private');
4761
+ assert(rootPackage.packageManager === \`pnpm@\${expectedPnpmVersion}\`, 'Root must pin pnpm');
4762
+ assert(rootPackage.modernjs?.preset === 'presetUltramodern', 'Root must declare presetUltramodern');
4763
+ assert(rootPackage.modernjs?.packageSource?.config === './.modernjs/ultramodern-package-source.json', 'Root must point at package source metadata');
4764
+ assert(rootPackage.modernjs?.packageSource?.strategy === packageSource.strategy, 'Root package source strategy must match metadata');
4765
+ assert(packageSource.strategy === 'workspace' || packageSource.strategy === 'install', 'Package source strategy must be workspace or install');
4766
+ assert(packageSource.generatedWorkspacePackages?.specifier === 'workspace:*', 'Generated workspace packages must keep workspace:* links');
4767
+ assert(
4768
+ rootPackage.scripts?.build ===
4769
+ 'pnpm -r --filter "./apps/remotes/**" run build && pnpm --filter "./apps/shell-super-app" run build && pnpm ultramodern:assert-mf-types',
4770
+ 'Root build script must build remotes before shell',
4771
+ );
4772
+ assert(rootPackage.scripts?.['ultramodern:check'] === 'node ./scripts/validate-ultramodern-workspace.mjs', 'Root must expose ultramodern:check');
4773
+ assert(rootPackage.scripts?.['ultramodern:assert-mf-types'] === 'node ./scripts/assert-mf-types.mjs', 'Root must expose ultramodern:assert-mf-types');
4774
+ assert(rootPackage.scripts?.['cloudflare:deploy']?.includes('run cloudflare:deploy'), 'Root must expose cloudflare:deploy');
4775
+ assert(rootPackage.scripts?.['cloudflare:proof'] === 'node ./scripts/proof-cloudflare-version.mjs --out .codex/reports/cloudflare-version-proof/public-url-proof.json', 'Root must expose cloudflare:proof');
4776
+
4777
+ const expectedAppIds = ['shell-super-app', ...fullStackVerticals.map(vertical => vertical.id)];
4778
+ assert(
4779
+ JSON.stringify(generatedContract.apps?.map(app => app.id)) === JSON.stringify(expectedAppIds),
4780
+ 'Generated contract must contain shell plus the Tractor full-stack remotes',
4781
+ );
4782
+ assert(generatedContract.cssFederation?.sharedDesignTokens?.owner?.id === 'shared-design-tokens', 'CSS federation must declare shared design token ownership');
4783
+ assert(generatedContract.cssFederation?.sharedDesignTokens?.role === 'shared-design-tokens', 'CSS federation must mark shared-design-tokens as token owner');
4784
+ assert(generatedContract.cssFederation?.sharedDesignTokens?.rootSelector === ':root', 'Shared design tokens must declare their root selector');
4785
+ assert(generatedContract.cssFederation?.sharedDesignTokens?.classPrefix === '--um-', 'Shared design tokens must declare their CSS custom property prefix');
4786
+ assert(generatedContract.cssFederation?.sharedDesignTokens?.layers?.owned?.includes('ultramodern-shared-tokens'), 'Shared design tokens must own the shared token CSS layer');
4787
+ assert(generatedContract.cssFederation?.sharedDesignTokens?.entrypoints?.css?.includes('packages/shared-design-tokens/src/tokens.css'), 'Shared design tokens must declare their CSS entrypoint');
4788
+ assert(generatedContract.cssFederation?.sharedDesignTokens?.assets?.exports?.includes('./tokens.css'), 'Shared design tokens must export their CSS asset');
4789
+ assert(generatedContract.cssFederation?.sharedDesignTokens?.dedupe?.duplicateBaseStylesAllowed === false, 'Shared design token CSS must be deduplicated');
4790
+ assert(generatedContract.cssFederation?.sharedDesignTokens?.ssr?.firstPaintRequired === true, 'Shared design token CSS must be required for SSR first paint');
4791
+
4792
+ const shellPackage = readJson('apps/shell-super-app/package.json');
4793
+ const expectedZephyrDependencies = Object.fromEntries(
4794
+ fullStackVerticals.map(vertical => [
4795
+ vertical.domain,
4796
+ \`\${vertical.packageName}@workspace:*\`,
4797
+ ]),
4798
+ );
4799
+ assert(
4800
+ JSON.stringify(shellPackage['zephyr:dependencies']) ===
4801
+ JSON.stringify(expectedZephyrDependencies),
4802
+ 'Shell Zephyr dependencies must reference every Tractor remote package',
4803
+ );
4804
+ const shellContract = generatedContract.apps?.find(app => app.id === 'shell-super-app');
4805
+ assert(shellContract?.deploy?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell Cloudflare workerName is incorrect');
4806
+ assert(shellContract?.deploy?.cloudflare?.publicUrlEnv === 'ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP', 'Shell Cloudflare public URL env is incorrect');
4807
+ assert(topology.shell?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell topology Cloudflare workerName is incorrect');
4808
+ assert(shellContract?.styling?.federation?.owner?.id === 'shell-super-app', 'Shell CSS federation owner is missing');
4809
+ assert(shellContract?.styling?.federation?.role === 'shell-base-overlay', 'Shell must own base and overlay CSS');
4810
+ assert(shellContract?.styling?.federation?.rootSelector === '[data-app-id="shell-super-app"]', 'Shell CSS root selector is incorrect');
4811
+ assert(shellContract?.styling?.federation?.classPrefix === 'shell-', 'Shell CSS class prefix is incorrect');
4812
+ assert(shellContract?.styling?.federation?.layers?.owned?.includes('ultramodern-shell-base'), 'Shell must own the base CSS layer');
4813
+ assert(shellContract?.styling?.federation?.layers?.owned?.includes('ultramodern-shell-overlay'), 'Shell must own the overlay CSS layer');
4814
+ assert(shellContract?.styling?.federation?.entrypoints?.css?.includes('src/routes/index.css'), 'Shell CSS entrypoint is missing');
4815
+ assert(shellContract?.styling?.federation?.assets?.shared?.some(asset => asset.endsWith('/shared-design-tokens/tokens.css')), 'Shell must import the shared design token CSS asset');
4816
+ assert(shellContract?.styling?.federation?.dedupe?.duplicateBaseStylesAllowed === false, 'Shell CSS contract must forbid duplicated base styles');
4817
+ assert(shellContract?.styling?.federation?.ssr?.firstPaintRequired === true, 'Shell CSS must be required for SSR first paint');
4818
+ assert(
4819
+ topology.shell?.remoteRefs?.join(',') === fullStackVerticals.map(vertical => vertical.id).join(','),
4820
+ 'Topology shell remoteRefs must match Tractor remotes',
4821
+ );
4822
+ assert(topology.remotes?.length === fullStackVerticals.length, 'Topology must contain only Tractor remotes');
4823
+ assert((topology.effectServices ?? []).length === 0, 'Default APIs must be vertical-owned, not effectServices');
4824
+
4825
+ for (const vertical of fullStackVerticals) {
4826
+ const packageJson = readJson(\`\${vertical.path}/package.json\`);
4827
+ assert(packageJson.name === vertical.packageName, \`\${vertical.id} package name is incorrect\`);
4828
+ assert(packageJson.scripts?.['cloudflare:deploy'] === 'MODERNJS_DEPLOY=cloudflare modern deploy', \`\${vertical.id} must expose cloudflare:deploy\`);
4829
+ assert(packageJson.scripts?.['cloudflare:proof']?.includes(\`--app \${vertical.id}\`), \`\${vertical.id} must expose cloudflare:proof\`);
4830
+ assert(packageJson.dependencies?.['@modern-js/plugin-bff'], \`\${vertical.id} must depend on plugin-bff\`);
4831
+ assert(packageJson.exports?.['./effect/client'] === \`./src/effect/\${vertical.stem}-client.ts\`, \`\${vertical.id} must export its Effect client\`);
4832
+ assert(packageJson.exports?.['./shared/effect/api'] === './shared/effect/api.ts', \`\${vertical.id} must export its Effect API contract\`);
4833
+ const expectedVerticalZephyrDependencies = Object.fromEntries(
4834
+ fullStackVerticals
4835
+ .filter(candidate => vertical.remoteRefs.includes(candidate.id))
4836
+ .map(candidate => [
4837
+ candidate.domain,
4838
+ \`\${candidate.packageName}@workspace:*\`,
4839
+ ]),
4840
+ );
4841
+ assert(
4842
+ JSON.stringify(packageJson['zephyr:dependencies']) ===
4843
+ JSON.stringify(expectedVerticalZephyrDependencies),
4844
+ \`\${vertical.id} Zephyr dependencies must match declared MF remote refs\`,
4845
+ );
4846
+
4847
+ const contractEntry = generatedContract.apps?.find(app => app.id === vertical.id);
4848
+ assert(contractEntry?.path === vertical.path, \`\${vertical.id} generated contract path is incorrect\`);
4849
+ assert(contractEntry?.kind === 'vertical', \`\${vertical.id} generated contract kind is incorrect\`);
4850
+ assert(contractEntry?.deploy?.cloudflare?.workerName === expectedWorkerName(vertical.id), \`\${vertical.id} Cloudflare workerName is incorrect\`);
4851
+ assert(contractEntry?.deploy?.cloudflare?.publicUrlEnv === \`ULTRAMODERN_PUBLIC_URL_\${vertical.id.replace(/-/g, '_').toUpperCase()}\`, \`\${vertical.id} Cloudflare public URL env is incorrect\`);
4852
+ assert(contractEntry?.deploy?.cloudflare?.routes?.effectReadiness === \`\${vertical.apiPrefix}/effect/\${vertical.stem}/readiness\`, \`\${vertical.id} Cloudflare proof readiness route is incorrect\`);
4853
+ assert(contractEntry?.moduleFederation?.name === vertical.mfName, \`\${vertical.id} MF name is incorrect\`);
4854
+ assert(JSON.stringify(contractEntry?.moduleFederation?.exposes) === JSON.stringify(vertical.exposes), \`\${vertical.id} MF exposes are incorrect\`);
4855
+ assert(contractEntry?.moduleFederation?.dts?.compilerInstance === '--package typescript -- tsc', \`\${vertical.id} must keep mandatory DTS compiler\`);
4856
+ assert(JSON.stringify(contractEntry?.moduleFederation?.remoteRefs ?? []) === JSON.stringify(vertical.remoteRefs), \`\${vertical.id} MF remoteRefs are incorrect\`);
4857
+ assert(
4858
+ JSON.stringify((contractEntry?.moduleFederation?.remotes ?? []).map(remote => remote.id)) ===
4859
+ JSON.stringify(vertical.remoteRefs),
4860
+ \`\${vertical.id} MF consumed remotes are incorrect\`,
4861
+ );
4862
+ assert(contractEntry?.effect?.prefix === vertical.apiPrefix, \`\${vertical.id} Effect API prefix is incorrect\`);
4863
+ assert(contractEntry?.effect?.group === vertical.group, \`\${vertical.id} Effect group is incorrect\`);
4864
+ assert(contractEntry?.effect?.readiness?.endpoint === \`/effect/\${vertical.stem}/readiness\`, \`\${vertical.id} readiness endpoint is incorrect\`);
4865
+ assert(contractEntry?.effect?.operations?.readiness?.path === \`/effect/\${vertical.stem}/readiness\`, \`\${vertical.id} readiness operation is missing\`);
4866
+ assert(contractEntry?.effect?.requestContext?.propagatedHeaders?.includes('traceparent'), \`\${vertical.id} trace context propagation is missing\`);
4867
+ assert(Object.keys(contractEntry?.effect?.domainOperations ?? {}).length >= 3, \`\${vertical.id} domain operations are missing\`);
4868
+ assert(contractEntry?.i18n?.languages?.includes('en') && contractEntry?.i18n?.languages?.includes('cs'), \`\${vertical.id} must declare i18n languages\`);
4869
+ assert(contractEntry?.i18n?.namespace === vertical.namespace, \`\${vertical.id} i18n namespace is incorrect\`);
4870
+ assert(
4871
+ JSON.stringify(contractEntry?.i18n?.localisedUrls) === JSON.stringify(vertical.localisedUrls),
4872
+ \`\${vertical.id} localisedUrls must come from route metadata\`,
4873
+ );
4874
+ assert(contractEntry?.routes?.source === 'route-owned', \`\${vertical.id} routes must be route-owned\`);
4875
+ assert(contractEntry?.routes?.metadataExport === './src/routes/ultramodern-route-metadata', \`\${vertical.id} route metadata export is incorrect\`);
4876
+ assert(contractEntry?.styling?.federation?.owner?.id === vertical.id, \`\${vertical.id} CSS federation owner is missing\`);
4877
+ assert(contractEntry?.styling?.federation?.role === 'vertical-remote-css', \`\${vertical.id} must own only vertical CSS\`);
4878
+ assert(contractEntry?.styling?.federation?.rootSelector === \`[data-app-id="\${vertical.id}"]\`, \`\${vertical.id} CSS root selector is incorrect\`);
4879
+ assert(contractEntry?.styling?.federation?.classPrefix === \`\${vertical.domain}-\`, \`\${vertical.id} CSS class prefix is incorrect\`);
4880
+ assert(contractEntry?.styling?.federation?.layers?.owned?.includes(\`ultramodern-remote-\${vertical.domain}\`), \`\${vertical.id} remote CSS layer is missing\`);
4881
+ assert(!contractEntry?.styling?.federation?.layers?.owned?.includes('ultramodern-shell-base'), \`\${vertical.id} must not own shell base CSS\`);
4882
+ assert(contractEntry?.styling?.federation?.entrypoints?.remoteEntry === 'src/remote-entry.tsx', \`\${vertical.id} remote CSS contract must include remote entry\`);
4883
+ assert(contractEntry?.styling?.federation?.assets?.shared?.some(asset => asset.endsWith('/shared-design-tokens/tokens.css')), \`\${vertical.id} must import shared design token CSS\`);
4884
+ assert(contractEntry?.styling?.federation?.dedupe?.runtimeLoad === 'once-per-content-hash', \`\${vertical.id} CSS dedupe strategy is incorrect\`);
4885
+ assert(contractEntry?.styling?.federation?.ssr?.remoteCss === 'remote-manifest-owned-css', \`\${vertical.id} SSR CSS loading contract is incorrect\`);
4886
+
4887
+ const topologyEntry = topology.remotes?.find(remote => remote.id === vertical.id);
4888
+ assert(topologyEntry?.kind === 'vertical', \`\${vertical.id} topology kind is incorrect\`);
4889
+ assert(topologyEntry?.package === vertical.packageName, \`\${vertical.id} topology package is incorrect\`);
4890
+ assert(topologyEntry?.cloudflare?.workerName === expectedWorkerName(vertical.id), \`\${vertical.id} topology Cloudflare workerName is incorrect\`);
4891
+ assert(topologyEntry?.moduleFederation?.name === vertical.mfName, \`\${vertical.id} topology MF name is incorrect\`);
4892
+ assert(JSON.stringify(topologyEntry?.moduleFederation?.exposes) === JSON.stringify(vertical.exposes), \`\${vertical.id} topology exposes are incorrect\`);
4893
+ assert(JSON.stringify(topologyEntry?.moduleFederation?.remoteRefs ?? []) === JSON.stringify(vertical.remoteRefs), \`\${vertical.id} topology remoteRefs are incorrect\`);
4894
+ assert(topologyEntry?.api?.effect?.bff?.prefix === vertical.apiPrefix, \`\${vertical.id} topology API prefix is incorrect\`);
4895
+ assert(topologyEntry?.api?.effect?.serverEntry === \`\${vertical.path}/api/effect/index.ts\`, \`\${vertical.id} topology server entry is incorrect\`);
4896
+ assert(topologyEntry?.api?.effect?.readiness?.endpoint === \`/effect/\${vertical.stem}/readiness\`, \`\${vertical.id} topology readiness endpoint is incorrect\`);
4897
+ assert(Object.keys(topologyEntry?.api?.effect?.domainOperations ?? {}).length >= 3, \`\${vertical.id} topology domain operations are missing\`);
4898
+
4899
+ assert(ownership.owners?.some(owner => owner.id === vertical.id && owner.path === vertical.path), \`\${vertical.id} ownership entry is missing\`);
4900
+ assert(overlay.ports?.[vertical.id], \`\${vertical.id} development port is missing\`);
4901
+ assert(overlay.manifests?.[vertical.id]?.includes('/mf-manifest.json'), \`\${vertical.id} development manifest is missing\`);
4902
+ assert(overlay.apis?.[vertical.id]?.endsWith(vertical.apiPrefix), \`\${vertical.id} development API URL is missing\`);
4903
+ }
4904
+
4905
+ console.log('UltraModern workspace scaffold validated');
4906
+ `;
4907
+ }
4908
+ function createCloudflareVersionProofScript() {
4909
+ return `#!/usr/bin/env node
4910
+ import fs from 'node:fs';
4911
+ import path from 'node:path';
4912
+
4913
+ const contractPath = '.modernjs/ultramodern-generated-contract.json';
4914
+ const defaultOut =
4915
+ '.codex/reports/cloudflare-version-proof/public-url-proof.json';
4916
+
4917
+ function readJson(relativePath) {
4918
+ return JSON.parse(fs.readFileSync(path.resolve(relativePath), 'utf8'));
4919
+ }
4920
+
4921
+ function parseArgs(argv) {
4922
+ const parsed = {
4923
+ appId: undefined,
4924
+ out: defaultOut,
4925
+ requirePublicUrls: false,
4926
+ };
4927
+
4928
+ for (let index = 0; index < argv.length; index += 1) {
4929
+ const arg = argv[index];
4930
+ if (arg === '--app') {
4931
+ parsed.appId = argv[index + 1];
4932
+ index += 1;
4933
+ } else if (arg === '--out') {
4934
+ parsed.out = argv[index + 1];
4935
+ index += 1;
4936
+ } else if (arg === '--require-public-urls') {
4937
+ parsed.requirePublicUrls = true;
4938
+ } else if (arg === '--help' || arg === '-h') {
4939
+ parsed.help = true;
4940
+ } else {
4941
+ throw new Error(\`Unknown argument: \${arg}\`);
4942
+ }
4943
+ }
4944
+
4945
+ return parsed;
4946
+ }
4947
+
4948
+ function printHelp() {
4949
+ process.stdout.write(\`Usage:
4950
+ node scripts/proof-cloudflare-version.mjs [--app remote-explore] [--out evidence.json] [--require-public-urls]
4951
+
4952
+ Set each app's public URL using the contract env key, for example:
4953
+ ULTRAMODERN_PUBLIC_URL_REMOTE_EXPLORE=https://remote-explore.example.workers.dev
4954
+ \`);
4955
+ }
4956
+
4957
+ function joinUrl(baseUrl, routePath) {
4958
+ return new URL(routePath, baseUrl.endsWith('/') ? baseUrl : \`\${baseUrl}/\`);
4959
+ }
4960
+
4961
+ async function fetchText(url) {
4962
+ const response = await fetch(url);
4963
+ return {
4964
+ ok: response.ok,
4965
+ status: response.status,
4966
+ contentType: response.headers.get('content-type'),
4967
+ body: await response.text(),
4968
+ };
4969
+ }
4970
+
4971
+ function parseMaybeJson(body) {
4972
+ try {
4973
+ return JSON.parse(body);
4974
+ } catch {
4975
+ return undefined;
4976
+ }
4977
+ }
4978
+
4979
+ function markerFromJson(value) {
4980
+ if (!value || typeof value !== 'object') {
4981
+ return undefined;
4982
+ }
4983
+ if (value.marker && typeof value.marker.build === 'string') {
4984
+ return value.marker.build;
4985
+ }
4986
+ if (typeof value.build === 'string') {
4987
+ return value.build;
4988
+ }
4989
+ for (const nested of Object.values(value)) {
4990
+ if (Array.isArray(nested)) {
4991
+ for (const item of nested) {
4992
+ const marker = markerFromJson(item);
4993
+ if (marker) {
4994
+ return marker;
4995
+ }
4996
+ }
4997
+ } else {
4998
+ const marker = markerFromJson(nested);
4999
+ if (marker) {
5000
+ return marker;
5001
+ }
5002
+ }
5003
+ }
5004
+ return undefined;
5005
+ }
5006
+
5007
+ function extractUiMarker(html) {
5008
+ return html.match(/data-build-marker=["']([^"']+)["']/u)?.[1];
5009
+ }
5010
+
5011
+ function assert(condition, message) {
5012
+ if (!condition) {
5013
+ throw new Error(message);
5014
+ }
5015
+ }
5016
+
5017
+ async function validateApp(app, publicUrl) {
5018
+ const cloudflare = app.deploy?.cloudflare;
5019
+ const routes = cloudflare?.routes ?? {};
5020
+ const evidence = {
5021
+ appId: app.id,
5022
+ publicUrl,
5023
+ workerName: cloudflare?.workerName,
5024
+ publicUrlEnv: cloudflare?.publicUrlEnv,
5025
+ assertions: [],
5026
+ };
5027
+
5028
+ const ssrRoute = routes.ssr ?? '/en';
5029
+ const ssr = await fetchText(joinUrl(publicUrl, ssrRoute));
5030
+ evidence.assertions.push({
5031
+ type: 'ssr',
5032
+ route: ssrRoute,
5033
+ status: ssr.ok ? 'pass' : 'fail',
5034
+ statusCode: ssr.status,
5035
+ });
5036
+ assert(ssr.ok, \`\${app.id} SSR route returned HTTP \${ssr.status}\`);
5037
+
5038
+ const uiMarker = extractUiMarker(ssr.body);
5039
+ evidence.assertions.push({
5040
+ type: 'ui-marker',
5041
+ expected: app.marker?.build,
5042
+ actual: uiMarker,
5043
+ status: uiMarker === app.marker?.build ? 'pass' : 'fail',
5044
+ });
5045
+ assert(uiMarker === app.marker?.build, \`\${app.id} UI marker mismatch\`);
5046
+
5047
+ const cssRootSelector = app.styling?.federation?.rootSelector;
5048
+ const expectedAppId = cssRootSelector?.match(/data-app-id="([^"]+)"/u)?.[1];
5049
+ evidence.assertions.push({
5050
+ type: 'css-root-marker',
5051
+ expected: cssRootSelector,
5052
+ status:
5053
+ expectedAppId && ssr.body.includes(\`data-app-id="\${expectedAppId}"\`)
5054
+ ? 'pass'
5055
+ : 'fail',
5056
+ });
5057
+ assert(
5058
+ expectedAppId && ssr.body.includes(\`data-app-id="\${expectedAppId}"\`),
5059
+ \`\${app.id} SSR response is missing CSS root marker \${cssRootSelector}\`,
5060
+ );
5061
+
5062
+ const manifestRoute = routes.mfManifest ?? '/mf-manifest.json';
5063
+ const manifest = await fetchText(joinUrl(publicUrl, manifestRoute));
5064
+ evidence.assertions.push({
5065
+ type: 'mf-manifest',
5066
+ route: manifestRoute,
5067
+ status: manifest.ok ? 'pass' : 'fail',
5068
+ statusCode: manifest.status,
5069
+ });
5070
+ assert(
5071
+ manifest.ok,
5072
+ \`\${app.id} MF manifest returned HTTP \${manifest.status}\`,
5073
+ );
5074
+
5075
+ const localeRoute = routes.locale ?? \`/locales/en/\${app.i18n?.namespace}.json\`;
5076
+ const locale = await fetchText(joinUrl(publicUrl, localeRoute));
5077
+ const localeJson = parseMaybeJson(locale.body);
5078
+ evidence.assertions.push({
5079
+ type: 'i18n-marker',
5080
+ namespace: app.i18n?.namespace,
5081
+ route: localeRoute,
5082
+ status:
5083
+ locale.ok &&
5084
+ localeJson &&
5085
+ Object.hasOwn(localeJson, app.i18n?.namespace)
5086
+ ? 'pass'
5087
+ : 'fail',
5088
+ statusCode: locale.status,
5089
+ });
5090
+ assert(locale.ok, \`\${app.id} locale JSON returned HTTP \${locale.status}\`);
5091
+ assert(
5092
+ localeJson && Object.hasOwn(localeJson, app.i18n?.namespace),
5093
+ \`\${app.id} locale JSON is missing namespace \${app.i18n?.namespace}\`,
5094
+ );
5095
+
5096
+ if (routes.effectReadiness) {
5097
+ const readiness = await fetchText(joinUrl(publicUrl, routes.effectReadiness));
5098
+ const readinessJson = parseMaybeJson(readiness.body);
5099
+ const apiMarker = markerFromJson(readinessJson);
5100
+ evidence.assertions.push({
5101
+ type: 'api-marker',
5102
+ route: routes.effectReadiness,
5103
+ expected: app.marker?.build,
5104
+ actual: apiMarker,
5105
+ status: readiness.ok && apiMarker === app.marker?.build ? 'pass' : 'fail',
5106
+ statusCode: readiness.status,
5107
+ });
5108
+ assert(
5109
+ readiness.ok,
5110
+ \`\${app.id} Effect readiness returned HTTP \${readiness.status}\`,
5111
+ );
5112
+ assert(apiMarker === app.marker?.build, \`\${app.id} API marker mismatch\`);
5113
+ }
5114
+
5115
+ return evidence;
5116
+ }
5117
+
5118
+ async function main(argv = process.argv.slice(2)) {
5119
+ const args = parseArgs(argv);
5120
+ if (args.help) {
5121
+ printHelp();
5122
+ return 0;
5123
+ }
5124
+
5125
+ const contract = readJson(contractPath);
5126
+ const apps = args.appId
5127
+ ? contract.apps.filter(app => app.id === args.appId)
5128
+ : contract.apps;
5129
+ assert(apps.length > 0, \`No generated app matched \${args.appId}\`);
5130
+
5131
+ const results = [];
5132
+ const skipped = [];
5133
+ for (const app of apps) {
5134
+ const publicUrlEnv = app.deploy?.cloudflare?.publicUrlEnv;
5135
+ const publicUrl = publicUrlEnv && process.env[publicUrlEnv];
5136
+ if (!publicUrl) {
5137
+ const skippedEntry = {
5138
+ appId: app.id,
5139
+ status: args.requirePublicUrls ? 'fail' : 'skipped',
5140
+ publicUrlEnv,
5141
+ reason: 'public URL environment variable is not set',
5142
+ };
5143
+ skipped.push(skippedEntry);
5144
+ if (args.requirePublicUrls) {
5145
+ throw new Error(\`\${app.id} requires \${publicUrlEnv}\`);
5146
+ }
5147
+ continue;
5148
+ }
5149
+ results.push(await validateApp(app, publicUrl));
5150
+ }
5151
+
5152
+ const report = {
5153
+ schemaVersion: 1,
5154
+ generatedAt: new Date().toISOString(),
5155
+ status: results.length > 0 ? 'pass' : 'skipped',
5156
+ contractPath,
5157
+ results,
5158
+ skipped,
5159
+ };
5160
+
5161
+ fs.mkdirSync(path.dirname(args.out), { recursive: true });
5162
+ fs.writeFileSync(args.out, \`\${JSON.stringify(report, null, 2)}\\n\`);
5163
+ process.stdout.write(
5164
+ \`[cloudflare-version-proof] \${report.status}: \${args.out}\\n\`,
5165
+ );
5166
+ return 0;
5167
+ }
5168
+
5169
+ main().then(
5170
+ exitCode => {
5171
+ process.exitCode = exitCode;
5172
+ },
5173
+ error => {
5174
+ process.stderr.write(\`[cloudflare-version-proof] \${error.message}\\n\`);
5175
+ process.exitCode = 1;
5176
+ },
5177
+ );
5178
+ `;
5179
+ }
5180
+ function writeGeneratedWorkspaceScripts(targetDir, scope, enableTailwind) {
5181
+ writeFileReplacing(targetDir, "scripts/assert-mf-types.mjs", createAssertMfTypesScript());
5182
+ writeFileReplacing(targetDir, "scripts/validate-ultramodern-workspace.mjs", createWorkspaceValidationScript(scope, enableTailwind));
5183
+ writeFileReplacing(targetDir, "scripts/proof-cloudflare-version.mjs", createCloudflareVersionProofScript());
5184
+ }
3562
5185
  function writeApp(targetDir, scope, app, packageSource, enableTailwind) {
3563
5186
  writeJson(targetDir, `${app.directory}/package.json`, createAppPackage(scope, app, packageSource, enableTailwind));
3564
5187
  writeJson(targetDir, `${app.directory}/tsconfig.json`, createPackageTsConfig(app.directory, appHasEffectApi(app)));
3565
- writeFile(targetDir, `${app.directory}/src/modern-app-env.d.ts`, "/// <reference types='@modern-js/app-tools/types' />\n\ndeclare const ULTRAMODERN_SITE_URL: string;\n");
5188
+ writeFile(targetDir, `${app.directory}/src/modern-app-env.d.ts`, createAppEnvDts(app));
3566
5189
  writeFile(targetDir, `${app.directory}/src/ultramodern-build.ts`, createUltramodernBuildModule(scope, app));
3567
- writeFile(targetDir, `${app.directory}/modern.config.ts`, createAppModernConfig(app));
5190
+ writeFile(targetDir, `${app.directory}/src/routes/ultramodern-route-metadata.ts`, createRouteMetadataModule(app));
5191
+ writeFile(targetDir, `${app.directory}/modern.config.ts`, createAppModernConfig(scope, app));
3568
5192
  writeFile(targetDir, `${app.directory}/src/modern.runtime.ts`, createAppRuntimeConfig(app));
3569
5193
  writeJson(targetDir, `${app.directory}/locales/en/translation.json`, createAppLocaleMessages(app, 'en'));
5194
+ writeJson(targetDir, `${app.directory}/locales/en/${appI18nNamespace(app)}.json`, createAppLocaleMessages(app, 'en'));
3570
5195
  writeJson(targetDir, `${app.directory}/locales/cs/translation.json`, createAppLocaleMessages(app, 'cs'));
3571
- writeFile(targetDir, `${app.directory}/src/routes/index.css`, createAppStyles(enableTailwind));
5196
+ writeJson(targetDir, `${app.directory}/locales/cs/${appI18nNamespace(app)}.json`, createAppLocaleMessages(app, 'cs'));
5197
+ writeFile(targetDir, `${app.directory}/src/routes/index.css`, createAppStyles(enableTailwind, scope, app));
3572
5198
  if (enableTailwind) {
3573
5199
  writeFile(targetDir, `${app.directory}/postcss.config.mjs`, createPostcssConfig());
3574
5200
  writeFile(targetDir, `${app.directory}/tailwind.config.ts`, createTailwindConfig());
@@ -3576,6 +5202,7 @@ function writeApp(targetDir, scope, app, packageSource, enableTailwind) {
3576
5202
  writeFile(targetDir, `${app.directory}/module-federation.config.ts`, 'shell' === app.kind ? createShellModuleFederationConfig() : createRemoteModuleFederationConfig(app));
3577
5203
  writeFile(targetDir, `${app.directory}/src/routes/layout.tsx`, createLayout(app.id));
3578
5204
  writeFile(targetDir, `${app.directory}/src/routes/[lang]/page.tsx`, 'shell' === app.kind ? createShellPage() : createRemotePage(app));
5205
+ for (const route of createRouteOwnedI18nPaths(app))if ('/' !== route.canonicalPath) writeFile(targetDir, createRoutePageFilePath(app, route.canonicalPath), createRouteAliasPage(route.canonicalPath));
3579
5206
  if ('shell' === app.kind) writeFile(targetDir, `${app.directory}/src/effect/recommendations-client.ts`, createShellEffectClient(scope));
3580
5207
  if (appHasEffectApi(app)) {
3581
5208
  writeFile(targetDir, `${app.directory}/shared/effect/api.ts`, createEffectSharedApi(app));
@@ -3584,7 +5211,10 @@ function writeApp(targetDir, scope, app, packageSource, enableTailwind) {
3584
5211
  }
3585
5212
  if ('vertical' === app.kind || 'horizontal-remote' === app.kind) {
3586
5213
  writeFile(targetDir, `${app.directory}/src/remote-entry.tsx`, createRemoteEntry(app));
3587
- writeFile(targetDir, `${app.directory}/src/components/${remoteWidgetFile(app)}.tsx`, createRemoteWidget(app));
5214
+ for (const expose of Object.keys(app.exposes ?? {})){
5215
+ const outputPath = remoteComponentOutputPath(app, expose);
5216
+ if (outputPath) writeFile(targetDir, outputPath, createRemoteExposeComponent(app, expose));
5217
+ }
3588
5218
  }
3589
5219
  if ('horizontal-design-system' === app.kind) {
3590
5220
  writeFile(targetDir, `${app.directory}/src/components/button.tsx`, createDesignButton());
@@ -3601,7 +5231,7 @@ function writeEffectService(targetDir, scope, packageSource, enableTailwind, ser
3601
5231
  return <main>${service.id} Effect service</main>;
3602
5232
  }
3603
5233
  `);
3604
- writeFile(targetDir, `${service.directory}/src/routes/index.css`, createAppStyles(enableTailwind));
5234
+ writeFile(targetDir, `${service.directory}/src/routes/index.css`, createServiceStyles(enableTailwind, scope, service));
3605
5235
  if (enableTailwind) {
3606
5236
  writeFile(targetDir, `${service.directory}/postcss.config.mjs`, createPostcssConfig());
3607
5237
  writeFile(targetDir, `${service.directory}/tailwind.config.ts`, createTailwindConfig());
@@ -3619,6 +5249,7 @@ function writeGenericSharedPackage(targetDir, scope, packageSource, sharedPackag
3619
5249
  });
3620
5250
  writeFile(targetDir, `${sharedPackage.directory}/src/index.ts`, `export const packageId = '${sharedPackage.id}';
3621
5251
  `);
5252
+ if ('shared-design-tokens' === sharedPackage.id) writeFile(targetDir, `${sharedPackage.directory}/src/tokens.css`, createSharedDesignTokensCss());
3622
5253
  }
3623
5254
  function writeSharedPackages(targetDir, scope, packageSource) {
3624
5255
  for (const sharedPackage of sharedPackages){
@@ -3644,6 +5275,7 @@ function writeSharedPackages(targetDir, scope, packageSource) {
3644
5275
  },
3645
5276
  } as const;
3646
5277
  `);
5278
+ writeFile(targetDir, 'packages/shared-design-tokens/src/tokens.css', createSharedDesignTokensCss());
3647
5279
  writeFile(targetDir, 'packages/shared-effect-api/src/index.ts', createEffectSharedApi());
3648
5280
  }
3649
5281
  function readJsonFile(filePath) {
@@ -3742,6 +5374,10 @@ function remoteTopologyEntry(scope, remote) {
3742
5374
  name: remote.mfName,
3743
5375
  manifestUrl: `http://localhost:${remote.port}/mf-manifest.json`,
3744
5376
  exposes: Object.keys(remote.exposes ?? {}),
5377
+ ...remote.remoteRefs?.length ? {
5378
+ remoteRefs: remote.remoteRefs,
5379
+ remotes: createModuleFederationRemoteContracts(remote)
5380
+ } : {},
3745
5381
  ssr: true,
3746
5382
  fallbackTelemetryEvent: 'modernjs:mv-runtime-parity',
3747
5383
  sharedContractVersion: 'mf-ssr-contract-v1'
@@ -3780,6 +5416,17 @@ function remotesFromTopology(topology, ports) {
3780
5416
  portEnv: '',
3781
5417
  port: 'number' == typeof ports[remote.id] ? ports[remote.id] : 0,
3782
5418
  mfName: remote.moduleFederation?.name ?? `remote${toPascalCase(remote.id)}`,
5419
+ ...Array.isArray(remote.moduleFederation?.exposes) ? {
5420
+ exposes: Object.fromEntries(remote.moduleFederation.exposes.map((expose)=>[
5421
+ expose,
5422
+ ''
5423
+ ]))
5424
+ } : {},
5425
+ ...Array.isArray(remote.moduleFederation?.remoteRefs) ? {
5426
+ remoteRefs: remote.moduleFederation.remoteRefs
5427
+ } : Array.isArray(remote.moduleFederation?.remotes) ? {
5428
+ remoteRefs: remote.moduleFederation.remotes.map((entry)=>entry.id).filter((id)=>'string' == typeof id)
5429
+ } : {},
3783
5430
  ...effectApi ? {
3784
5431
  effectApi
3785
5432
  } : {},
@@ -3837,7 +5484,10 @@ function addUltramodernMicroVertical(options) {
3837
5484
  writeJsonFile(ownershipPath, ownership);
3838
5485
  writeJsonFile(overlayPath, overlay);
3839
5486
  writeJsonFile(node_path.join(options.workspaceRoot, GENERATED_CONTRACT_PATH), createGeneratedContract(scope, [
3840
- shellApp,
5487
+ {
5488
+ ...shellApp,
5489
+ remoteRefs: remotesFromTopology(topology, overlay.ports).map((remote)=>remote.id)
5490
+ },
3841
5491
  ...remotesFromTopology(topology, overlay.ports)
3842
5492
  ], enableTailwind));
3843
5493
  const shellConfigPath = node_path.join(options.workspaceRoot, `${shellApp.directory}/module-federation.config.ts`);
@@ -3940,6 +5590,7 @@ function generateUltramodernWorkspace(options) {
3940
5590
  writeApp(options.targetDir, scope, shellApp, packageSource, enableTailwind);
3941
5591
  for (const remote of remoteApps)writeApp(options.targetDir, scope, remote, packageSource, enableTailwind);
3942
5592
  writeSharedPackages(options.targetDir, scope, packageSource);
5593
+ writeGeneratedWorkspaceScripts(options.targetDir, scope, enableTailwind);
3943
5594
  }
3944
5595
  const src_dirname = node_path.dirname(fileURLToPath(import.meta.url));
3945
5596
  const templateDir = node_path.resolve(src_dirname, '..', 'template');