@bleedingdev/modern-js-create 3.2.0-ultramodern.102 → 3.2.0-ultramodern.104

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
@@ -559,6 +559,64 @@ const localeKeys = i18n.init('en', {
559
559
  zh: ZH_LOCALE,
560
560
  en: EN_LOCALE
561
561
  });
562
+ const WORKSPACE_PACKAGE_VERSION = 'workspace:*';
563
+ const BLEEDINGDEV_CREATE_PACKAGE = '@bleedingdev/modern-js-create';
564
+ const BLEEDINGDEV_PACKAGE_SCOPE = 'bleedingdev';
565
+ const BLEEDINGDEV_PACKAGE_NAME_PREFIX = 'modern-js-';
566
+ const BLEEDINGDEV_FRAMEWORK_VERSION_ENV = 'MODERN_CREATE_ULTRAMODERN_FRAMEWORK_VERSION';
567
+ const ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES = [
568
+ '@modern-js/runtime',
569
+ '@modern-js/app-tools',
570
+ '@modern-js/tsconfig',
571
+ '@modern-js/plugin-i18n',
572
+ '@modern-js/plugin-tanstack',
573
+ '@modern-js/plugin-bff',
574
+ '@modern-js/adapter-rstest'
575
+ ];
576
+ const ULTRAMODERN_WORKSPACE_MODERN_PACKAGES = [
577
+ '@modern-js/app-tools',
578
+ '@modern-js/plugin-bff',
579
+ '@modern-js/plugin-i18n',
580
+ '@modern-js/plugin-tanstack',
581
+ '@modern-js/runtime'
582
+ ];
583
+ function modernPackageVersion(packageSource) {
584
+ return 'install' === packageSource.strategy ? packageSource.modernPackageVersion : WORKSPACE_PACKAGE_VERSION;
585
+ }
586
+ function modernAliasPackageName(packageName, packageSource) {
587
+ if (!packageSource.aliasScope) return packageName;
588
+ const scope = packageSource.aliasScope.replace(/^@/, '');
589
+ const unscopedName = packageName.split('/').at(-1);
590
+ return `@${scope}/${packageSource.aliasPackageNamePrefix ?? ''}${unscopedName}`;
591
+ }
592
+ function modernPackageSpecifier(packageName, packageSource) {
593
+ if ('install' !== packageSource.strategy) return WORKSPACE_PACKAGE_VERSION;
594
+ if (!packageSource.aliasScope) return packageSource.modernPackageVersion;
595
+ return `npm:${modernAliasPackageName(packageName, packageSource)}@${packageSource.modernPackageVersion}`;
596
+ }
597
+ function modernPackageAliases(packageNames, packageSource) {
598
+ if (!packageSource.aliasScope) return;
599
+ return Object.fromEntries(packageNames.map((packageName)=>[
600
+ packageName,
601
+ modernAliasPackageName(packageName, packageSource)
602
+ ]));
603
+ }
604
+ function createModernPackagesMetadata(packageNames, packageSource, options = {}) {
605
+ const includeAliases = options.includeAliases ?? Boolean(packageSource.aliasScope);
606
+ const aliases = includeAliases ? modernPackageAliases(packageNames, packageSource) : void 0;
607
+ return {
608
+ packages: [
609
+ ...packageNames
610
+ ],
611
+ specifier: modernPackageVersion(packageSource),
612
+ ...packageSource.registry ? {
613
+ registry: packageSource.registry
614
+ } : {},
615
+ ...aliases ? {
616
+ aliases
617
+ } : {}
618
+ };
619
+ }
562
620
  const ultramodern_workspace_dirname = node_path.dirname(fileURLToPath(import.meta.url));
563
621
  const workspaceTemplateDir = node_path.resolve(ultramodern_workspace_dirname, '..', 'template-workspace');
564
622
  const TANSTACK_ROUTER_VERSION = '1.170.11';
@@ -566,6 +624,7 @@ const MODULE_FEDERATION_VERSION = '2.5.0';
566
624
  const ZEPHYR_RSPACK_PLUGIN_VERSION = '1.1.1';
567
625
  const ZEPHYR_AGENT_VERSION = '1.1.1';
568
626
  const WRANGLER_VERSION = '4.95.0';
627
+ const CLOUDFLARE_COMPATIBILITY_DATE = '2026-06-02';
569
628
  const TAILWIND_VERSION = '4.3.0';
570
629
  const TAILWIND_POSTCSS_VERSION = '4.3.0';
571
630
  const EFFECT_TSGO_VERSION = '0.13.0';
@@ -580,7 +639,6 @@ const REACT_VERSION = '^19.2.6';
580
639
  const REACT_DOM_VERSION = '^19.2.6';
581
640
  const REACT_ROUTER_DOM_VERSION = '7.16.0';
582
641
  const PNPM_VERSION = '11.5.0';
583
- const WORKSPACE_PACKAGE_VERSION = 'workspace:*';
584
642
  const GENERATED_CONTRACT_PATH = '.modernjs/ultramodern-generated-contract.json';
585
643
  const RSTACK_AGENT_SKILLS_COMMIT = '61c948b42512e223bad44b83af4080eba48b2677';
586
644
  const MODULE_FEDERATION_AGENT_SKILLS_COMMIT = '07bb5b6c43ad457609e00c081b72d4c42508ec76';
@@ -604,13 +662,6 @@ const privateAgentSkills = [
604
662
  'debugger-mode'
605
663
  ];
606
664
  const effectTsgoTypecheckCommand = "node -e \"const fs = require('node:fs'); const { execFileSync, spawnSync } = require('node:child_process'); const bin = execFileSync('effect-tsgo', ['get-exe-path'], { encoding: 'utf8' }).trim(); if (process.platform !== 'win32') fs.chmodSync(bin, 0o755); const result = spawnSync(bin, ['--noEmit', '-p', 'tsconfig.json'], { stdio: 'inherit' }); process.exit(result.status ?? 1);\"";
607
- const modernPackageNames = [
608
- '@modern-js/app-tools',
609
- '@modern-js/plugin-bff',
610
- '@modern-js/plugin-i18n',
611
- '@modern-js/plugin-tanstack',
612
- '@modern-js/runtime'
613
- ];
614
665
  function sortJsonValue(value) {
615
666
  if (Array.isArray(value)) return value.map(sortJsonValue);
616
667
  if (null !== value && 'object' == typeof value) return Object.fromEntries(Object.entries(value).sort(([left], [right])=>left.localeCompare(right)).map(([key, entry])=>[
@@ -619,6 +670,10 @@ function sortJsonValue(value) {
619
670
  ]));
620
671
  return value;
621
672
  }
673
+ const supportedWorkspaceLanguages = [
674
+ 'en',
675
+ 'cs'
676
+ ];
622
677
  const ULTRAMODERN_WORKSPACE_FLAG = '--ultramodern-workspace';
623
678
  const FIRST_VERTICAL_PORT = 4101;
624
679
  const TAILWIND_PREFIX_DIGIT_WORDS = [
@@ -913,28 +968,23 @@ function relativeRootFor(packageDir) {
913
968
  return normalizePath(node_path.relative(packageDir, '.') || '.');
914
969
  }
915
970
  function resolvePackageSource(options) {
916
- const strategy = options.packageSource?.strategy ?? 'workspace';
917
- return {
971
+ const strategy = options.packageSource?.strategy ?? 'install';
972
+ if ('workspace' === strategy) return {
918
973
  strategy,
919
- modernPackageVersion: 'install' === strategy ? options.packageSource?.modernPackageVersion ?? options.modernVersion : WORKSPACE_PACKAGE_VERSION,
974
+ modernPackageVersion: WORKSPACE_PACKAGE_VERSION,
920
975
  registry: options.packageSource?.registry,
921
976
  aliasScope: options.packageSource?.aliasScope,
922
977
  aliasPackageNamePrefix: options.packageSource?.aliasPackageNamePrefix
923
978
  };
924
- }
925
- function modernPackageVersion(packageSource) {
926
- return 'install' === packageSource.strategy ? packageSource.modernPackageVersion : WORKSPACE_PACKAGE_VERSION;
927
- }
928
- function modernAliasPackageName(packageName, packageSource) {
929
- if (!packageSource.aliasScope) return packageName;
930
- const scope = packageSource.aliasScope.replace(/^@/, '');
931
- const unscopedName = packageName.split('/').at(-1);
932
- return `@${scope}/${packageSource.aliasPackageNamePrefix ?? ''}${unscopedName}`;
933
- }
934
- function modernPackageSpecifier(packageName, packageSource) {
935
- if ('install' !== packageSource.strategy) return WORKSPACE_PACKAGE_VERSION;
936
- if (!packageSource.aliasScope) return packageSource.modernPackageVersion;
937
- return `npm:${modernAliasPackageName(packageName, packageSource)}@${packageSource.modernPackageVersion}`;
979
+ const registry = options.packageSource?.registry;
980
+ const aliasScope = options.packageSource?.aliasScope ?? (registry ? void 0 : BLEEDINGDEV_PACKAGE_SCOPE);
981
+ return {
982
+ strategy,
983
+ modernPackageVersion: options.packageSource?.modernPackageVersion ?? options.modernVersion,
984
+ registry,
985
+ aliasScope,
986
+ aliasPackageNamePrefix: options.packageSource?.aliasPackageNamePrefix ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
987
+ };
938
988
  }
939
989
  function appDependencies(scope, packageSource, app, remotes = []) {
940
990
  const dependencies = {
@@ -1101,17 +1151,105 @@ function createCloudflareProofRoute(app) {
1101
1151
  } : {}
1102
1152
  };
1103
1153
  }
1154
+ function createCloudflareSecurityContract() {
1155
+ return {
1156
+ enabled: true,
1157
+ headers: {
1158
+ referrerPolicy: 'strict-origin-when-cross-origin',
1159
+ contentTypeOptions: 'nosniff',
1160
+ permissionsPolicy: 'camera=(), geolocation=(), microphone=(), payment=(), usb=()'
1161
+ },
1162
+ contentSecurityPolicy: {
1163
+ mode: 'report-only',
1164
+ directives: {
1165
+ 'base-uri': [
1166
+ "'self'"
1167
+ ],
1168
+ 'connect-src': [
1169
+ "'self'",
1170
+ 'https:',
1171
+ 'http:',
1172
+ 'wss:',
1173
+ 'ws:'
1174
+ ],
1175
+ 'default-src': [
1176
+ "'self'"
1177
+ ],
1178
+ 'font-src': [
1179
+ "'self'",
1180
+ 'data:',
1181
+ 'https:',
1182
+ 'http:'
1183
+ ],
1184
+ 'form-action': [
1185
+ "'self'"
1186
+ ],
1187
+ 'frame-ancestors': [
1188
+ "'self'"
1189
+ ],
1190
+ 'img-src': [
1191
+ "'self'",
1192
+ 'data:',
1193
+ 'blob:',
1194
+ 'https:',
1195
+ 'http:'
1196
+ ],
1197
+ 'manifest-src': [
1198
+ "'self'",
1199
+ 'https:',
1200
+ 'http:'
1201
+ ],
1202
+ 'object-src': [
1203
+ "'none'"
1204
+ ],
1205
+ "script-src": [
1206
+ "'self'",
1207
+ "'unsafe-inline'",
1208
+ "'unsafe-eval'",
1209
+ 'https:',
1210
+ 'http:',
1211
+ 'blob:'
1212
+ ],
1213
+ 'style-src': [
1214
+ "'self'",
1215
+ "'unsafe-inline'",
1216
+ 'https:',
1217
+ 'http:'
1218
+ ],
1219
+ 'worker-src': [
1220
+ "'self'",
1221
+ 'blob:'
1222
+ ]
1223
+ },
1224
+ reason: "Report-only by default so Cloudflare Module Federation SSR can prove remote script, style, and connect compatibility before enforcement."
1225
+ },
1226
+ noindex: {
1227
+ workersDev: true,
1228
+ localhost: true,
1229
+ previewHostnames: []
1230
+ },
1231
+ cookies: {
1232
+ mutateSetCookie: false,
1233
+ reason: 'Generated Cloudflare worker does not own application Set-Cookie headers.'
1234
+ }
1235
+ };
1236
+ }
1237
+ function formatTsJsonValue(value, indent) {
1238
+ return JSON.stringify(value, null, 2).replaceAll('\n', `\n${' '.repeat(indent)}`);
1239
+ }
1104
1240
  function createCloudflareDeployContract(scope, app) {
1105
1241
  return {
1106
1242
  target: 'cloudflare',
1107
1243
  workerName: createCloudflareWorkerName(scope, app),
1108
1244
  publicUrlEnv: createCloudflarePublicUrlEnv(app),
1245
+ compatibilityDate: CLOUDFLARE_COMPATIBILITY_DATE,
1109
1246
  compatibilityFlags: [
1110
1247
  'nodejs_compat',
1111
1248
  'global_fetch_strictly_public'
1112
1249
  ],
1113
1250
  assetsBinding: 'ASSETS',
1114
1251
  routes: createCloudflareProofRoute(app),
1252
+ security: createCloudflareSecurityContract(),
1115
1253
  evidence: {
1116
1254
  proofScript: "scripts/proof-cloudflare-version.mjs",
1117
1255
  reportDefault: '.codex/reports/cloudflare-version-proof/public-url-proof.json'
@@ -1331,7 +1469,19 @@ if (
1331
1469
  export default defineConfig(
1332
1470
  presetUltramodern(
1333
1471
  {
1334
- ${bffConfig} html: {
1472
+ ${bffConfig} ...(cloudflareDeployEnabled
1473
+ ? {
1474
+ deploy: {
1475
+ worker: {
1476
+ compatibilityDate: '${CLOUDFLARE_COMPATIBILITY_DATE}',
1477
+ name: cloudflareWorkerName,
1478
+ security: ${formatTsJsonValue(sortJsonValue(createCloudflareSecurityContract()), 16)},
1479
+ ssr: true,
1480
+ },
1481
+ },
1482
+ }
1483
+ : {}),
1484
+ html: {
1335
1485
  outputStructure: 'flat',
1336
1486
  },
1337
1487
  output: {
@@ -1368,6 +1518,9 @@ ${bffConfig} html: {
1368
1518
  '/mf-manifest.json',
1369
1519
  '/mf-stats.json',
1370
1520
  '/remoteEntry.js',
1521
+ '/robots.txt',
1522
+ '/site.webmanifest',
1523
+ '/sitemap.xml',
1371
1524
  '/static',
1372
1525
  '/zephyr-manifest.json',
1373
1526
  ],
@@ -1380,6 +1533,20 @@ ${bffConfig} html: {
1380
1533
  ${bffPluginEntry} moduleFederationPlugin(),
1381
1534
  zephyrRspackPlugin(),
1382
1535
  ],
1536
+ server: {
1537
+ port,
1538
+ publicDir: ['./locales', './assets'],
1539
+ ssr: {
1540
+ mode: 'string',
1541
+ moduleFederationAppSSR: true,
1542
+ },
1543
+ },
1544
+ source: {
1545
+ globalVars: {
1546
+ ULTRAMODERN_SITE_URL: siteUrl,
1547
+ },
1548
+ mainEntryName: 'index',
1549
+ },
1383
1550
  tools: {
1384
1551
  autoprefixer: {
1385
1552
  overrideBrowserslist: ['defaults'],
@@ -1396,29 +1563,6 @@ ${bffPluginEntry} moduleFederationPlugin(),
1396
1563
  ]);
1397
1564
  },
1398
1565
  },
1399
- ...(cloudflareDeployEnabled
1400
- ? {
1401
- deploy: {
1402
- worker: {
1403
- ssr: true,
1404
- },
1405
- },
1406
- }
1407
- : {}),
1408
- server: {
1409
- port,
1410
- publicDir: ['./locales', './assets'],
1411
- ssr: {
1412
- mode: 'string',
1413
- moduleFederationAppSSR: true,
1414
- },
1415
- },
1416
- source: {
1417
- globalVars: {
1418
- ULTRAMODERN_SITE_URL: siteUrl,
1419
- },
1420
- mainEntryName: 'index',
1421
- },
1422
1566
  },
1423
1567
  {
1424
1568
  appId,
@@ -1638,12 +1782,18 @@ ${createModuleFederationRemotesConfig(scope, app, remotes)}${createSharedModuleF
1638
1782
  function appI18nNamespace(app) {
1639
1783
  return 'shell' === app.kind ? 'shell' : app.domain ?? app.id;
1640
1784
  }
1785
+ const privateAppRoutePublicness = {
1786
+ indexable: false,
1787
+ public: false,
1788
+ publicSurface: 'private-app-screen'
1789
+ };
1641
1790
  function createRouteOwnedI18nPaths(app) {
1642
1791
  const namespace = appI18nNamespace(app);
1643
1792
  const base = {
1644
1793
  mfBoundaryId: app.mfName,
1645
1794
  namespace,
1646
- ownerAppId: app.id
1795
+ ownerAppId: app.id,
1796
+ ...privateAppRoutePublicness
1647
1797
  };
1648
1798
  if ('shell' === app.kind) return [
1649
1799
  {
@@ -1816,8 +1966,11 @@ function createRouteOwnedI18nPaths(app) {
1816
1966
  }
1817
1967
  ];
1818
1968
  }
1819
- function createLocalisedUrlsMap(app) {
1820
- return Object.fromEntries(createRouteOwnedI18nPaths(app).flatMap((route)=>{
1969
+ function isPublicIndexableRoute(route) {
1970
+ return route.public && route.indexable;
1971
+ }
1972
+ function createLocalisedUrlsMapFromRoutes(routes) {
1973
+ return Object.fromEntries(routes.flatMap((route)=>{
1821
1974
  if ('/' === route.canonicalPath) return [];
1822
1975
  return Array.from(new Set([
1823
1976
  route.canonicalPath,
@@ -1828,9 +1981,23 @@ function createLocalisedUrlsMap(app) {
1828
1981
  ]);
1829
1982
  }));
1830
1983
  }
1984
+ function createLocalisedUrlsMap(app) {
1985
+ return createLocalisedUrlsMapFromRoutes(createRouteOwnedI18nPaths(app));
1986
+ }
1987
+ function createPublicRouteMetadata(app) {
1988
+ return createRouteOwnedI18nPaths(app).filter(isPublicIndexableRoute).map((route)=>({
1989
+ canonicalPath: route.canonicalPath,
1990
+ id: route.id,
1991
+ localisedPaths: route.localisedPaths,
1992
+ namespace: route.namespace,
1993
+ ownerAppId: route.ownerAppId,
1994
+ titleKey: route.titleKey
1995
+ }));
1996
+ }
1831
1997
  function createRouteMetadataModule(app) {
1832
1998
  const routes = sortJsonValue(createRouteOwnedI18nPaths(app));
1833
1999
  const localisedUrls = sortJsonValue(createLocalisedUrlsMap(app));
2000
+ const publicRoutes = sortJsonValue(createPublicRouteMetadata(app));
1834
2001
  const namespace = appI18nNamespace(app);
1835
2002
  return `export const ultramodernRouteNamespace = '${namespace}' as const;
1836
2003
 
@@ -1838,9 +2005,12 @@ export const ultramodernRouteMetadata = ${JSON.stringify(routes, null, 2)} as co
1838
2005
 
1839
2006
  export const ultramodernLocalisedUrls = ${JSON.stringify(localisedUrls, null, 2)} as const;
1840
2007
 
2008
+ export const ultramodernPublicRoutes = ${JSON.stringify(publicRoutes, null, 2)} as const;
2009
+
1841
2010
  export const ultramodernRouteConfig = {
1842
2011
  localisedUrls: ultramodernLocalisedUrls,
1843
2012
  namespace: ultramodernRouteNamespace,
2013
+ publicRoutes: ultramodernPublicRoutes,
1844
2014
  routes: ultramodernRouteMetadata,
1845
2015
  source: 'route-owned',
1846
2016
  } as const;
@@ -2011,15 +2181,125 @@ function createPostcssConfig() {
2011
2181
  function createTailwindConfig() {
2012
2182
  return `import type { Config } from 'tailwindcss';
2013
2183
 
2014
- export default {
2015
- } satisfies Config;
2184
+ export default {} satisfies Config;
2016
2185
  `;
2017
2186
  }
2018
2187
  function createTw(prefix) {
2019
2188
  return (classList)=>classList.split(/\s+/u).filter(Boolean).map((candidate)=>`${prefix}:${candidate.replace(/\[&&\]:/gu, '')}`).join(' ');
2020
2189
  }
2021
- function workspaceAssetsForApp(_app) {
2022
- return {};
2190
+ const publicSurfaceRequiredAssetPaths = [
2191
+ 'config/public/robots.txt'
2192
+ ];
2193
+ const publicSurfaceOptionalAssetPaths = [
2194
+ 'config/public/sitemap.xml',
2195
+ 'config/public/site.webmanifest'
2196
+ ];
2197
+ function normalisePublicPath(pathname) {
2198
+ const normalised = pathname.trim().replaceAll(/\/+/gu, '/').replace(/\/+$/u, '');
2199
+ return normalised.length > 0 && normalised.startsWith('/') ? normalised : `/${normalised}`;
2200
+ }
2201
+ function createLocalisedPublicPath(pathname, language) {
2202
+ const publicPath = normalisePublicPath(pathname);
2203
+ return '/' === publicPath ? `/${language}` : `/${language}${publicPath}`;
2204
+ }
2205
+ function isConcretePublicPath(pathname) {
2206
+ return !normalisePublicPath(pathname).split('/').some((segment)=>segment.startsWith(':') || segment.includes('*') || segment.startsWith('['));
2207
+ }
2208
+ function uniqueSorted(values) {
2209
+ return Array.from(new Set(values)).sort((left, right)=>left.localeCompare(right));
2210
+ }
2211
+ function createPublicSurfaceRouteEntries(app) {
2212
+ return createPublicRouteMetadata(app).map((route)=>{
2213
+ const localeUrlPaths = Object.fromEntries(supportedWorkspaceLanguages.map((language)=>[
2214
+ language,
2215
+ createLocalisedPublicPath(route.localisedPaths[language], language)
2216
+ ]));
2217
+ if (!Object.values(localeUrlPaths).every(isConcretePublicPath)) return;
2218
+ return {
2219
+ ...route,
2220
+ canonicalUrlPath: localeUrlPaths.en,
2221
+ localeUrlPaths
2222
+ };
2223
+ }).filter((route)=>void 0 !== route).sort((left, right)=>left.canonicalUrlPath.localeCompare(right.canonicalUrlPath) || left.id.localeCompare(right.id));
2224
+ }
2225
+ function createPublicSurfaceUrlPaths(app) {
2226
+ return uniqueSorted(createPublicSurfaceRouteEntries(app).flatMap((route)=>supportedWorkspaceLanguages.map((language)=>route.localeUrlPaths[language])));
2227
+ }
2228
+ function createPublicSurfaceOrigin(app) {
2229
+ return `http://localhost:${app.port}`;
2230
+ }
2231
+ function escapeXmlText(value) {
2232
+ return value.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;');
2233
+ }
2234
+ function escapeXmlAttribute(value) {
2235
+ return escapeXmlText(value).replaceAll('"', '&quot;');
2236
+ }
2237
+ function renderRobotsTxt(app) {
2238
+ const urlPaths = createPublicSurfaceUrlPaths(app);
2239
+ const lines = [
2240
+ 'User-agent: *'
2241
+ ];
2242
+ if (0 === urlPaths.length) lines.push('Disallow: /');
2243
+ else {
2244
+ for (const urlPath of urlPaths)lines.push(`Allow: ${urlPath}$`);
2245
+ lines.push('Disallow: /');
2246
+ lines.push(`Sitemap: ${createPublicSurfaceOrigin(app)}/sitemap.xml`);
2247
+ }
2248
+ return `${lines.join('\n')}\n`;
2249
+ }
2250
+ function renderSitemapXml(app) {
2251
+ const origin = createPublicSurfaceOrigin(app);
2252
+ const routes = createPublicSurfaceRouteEntries(app);
2253
+ const lines = [
2254
+ '<?xml version="1.0" encoding="UTF-8"?>',
2255
+ '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">'
2256
+ ];
2257
+ for (const route of routes)for (const language of supportedWorkspaceLanguages){
2258
+ lines.push(' <url>');
2259
+ lines.push(` <loc>${escapeXmlText(`${origin}${route.localeUrlPaths[language]}`)}</loc>`);
2260
+ for (const alternateLanguage of supportedWorkspaceLanguages)lines.push(` <xhtml:link rel="alternate" hreflang="${alternateLanguage}" href="${escapeXmlAttribute(`${origin}${route.localeUrlPaths[alternateLanguage]}`)}" />`);
2261
+ lines.push(` <xhtml:link rel="alternate" hreflang="x-default" href="${escapeXmlAttribute(`${origin}${route.localeUrlPaths.en}`)}" />`);
2262
+ lines.push(' </url>');
2263
+ }
2264
+ lines.push('</urlset>');
2265
+ return `${lines.join('\n')}\n`;
2266
+ }
2267
+ function renderWebManifest(app) {
2268
+ const startUrl = createPublicSurfaceUrlPaths(app)[0];
2269
+ const manifest = {
2270
+ name: app.displayName,
2271
+ short_name: app.displayName,
2272
+ display: 'standalone',
2273
+ background_color: '#ffffff',
2274
+ theme_color: '#133225',
2275
+ lang: 'en',
2276
+ categories: [
2277
+ 'business',
2278
+ 'productivity'
2279
+ ],
2280
+ icons: [],
2281
+ ...startUrl ? {
2282
+ scope: '/',
2283
+ start_url: startUrl
2284
+ } : {}
2285
+ };
2286
+ return `${JSON.stringify(sortJsonValue(manifest), null, 2)}\n`;
2287
+ }
2288
+ function createPublicSurfaceAssets(app) {
2289
+ const assets = {
2290
+ 'config/public/robots.txt': renderRobotsTxt(app)
2291
+ };
2292
+ if (createPublicSurfaceRouteEntries(app).length > 0) {
2293
+ assets['config/public/sitemap.xml'] = renderSitemapXml(app);
2294
+ assets['config/public/site.webmanifest'] = renderWebManifest(app);
2295
+ }
2296
+ return assets;
2297
+ }
2298
+ function workspaceAssetsForApp(app) {
2299
+ return createPublicSurfaceAssets(app);
2300
+ }
2301
+ function rewriteWorkspaceAssetsForApp(workspaceRoot, app) {
2302
+ for (const [relativePath, content] of Object.entries(workspaceAssetsForApp(app)))writeFileReplacing(workspaceRoot, `${app.directory}/${relativePath}`, content);
2023
2303
  }
2024
2304
  function createLocalizedHeadComponent() {
2025
2305
  return `const fallbackLanguage = 'en';
@@ -3969,19 +4249,10 @@ function createDevelopmentOverlay(remotes = []) {
3969
4249
  };
3970
4250
  }
3971
4251
  function createPackageSourceMetadata(scope, packageSource) {
3972
- const modernPackages = {
3973
- packages: modernPackageNames,
3974
- specifier: modernPackageVersion(packageSource)
3975
- };
3976
- if (packageSource.registry) modernPackages.registry = packageSource.registry;
3977
- if (packageSource.aliasScope) modernPackages.aliases = Object.fromEntries(modernPackageNames.map((packageName)=>[
3978
- packageName,
3979
- modernAliasPackageName(packageName, packageSource)
3980
- ]));
3981
4252
  return {
3982
4253
  schemaVersion: 1,
3983
4254
  strategy: packageSource.strategy,
3984
- modernPackages,
4255
+ modernPackages: createModernPackagesMetadata(ULTRAMODERN_WORKSPACE_MODERN_PACKAGES, packageSource),
3985
4256
  generatedWorkspacePackages: {
3986
4257
  packages: sharedPackages.map((sharedPackage)=>ultramodern_workspace_packageName(scope, sharedPackage.id)),
3987
4258
  specifier: WORKSPACE_PACKAGE_VERSION
@@ -4231,6 +4502,23 @@ function createStylingContract(scope, app, enableTailwind) {
4231
4502
  federation: createAppCssFederationContract(scope, app)
4232
4503
  };
4233
4504
  }
4505
+ function createPublicSurfaceContract(app) {
4506
+ const files = Object.keys(createPublicSurfaceAssets(app)).sort().map((relativePath)=>relativePath.replace(/^config\/public\//u, ''));
4507
+ return {
4508
+ source: 'route-owned-public-routes',
4509
+ metadataExport: './src/routes/ultramodern-route-metadata',
4510
+ staticRoot: 'config/public',
4511
+ privateRoutePolicy: 'omit-from-generated-public-surface',
4512
+ files,
4513
+ omittedByDefault: [
4514
+ 'api-catalog.json',
4515
+ 'llms.txt',
4516
+ 'security.txt'
4517
+ ],
4518
+ publicRoutes: createPublicRouteMetadata(app),
4519
+ concreteUrlPaths: createPublicSurfaceUrlPaths(app)
4520
+ };
4521
+ }
4234
4522
  function createAppGeneratedContract(scope, app, apps, enableTailwind) {
4235
4523
  const appWithResolvedRefs = 'shell' === app.kind ? {
4236
4524
  ...app,
@@ -4248,7 +4536,9 @@ function createAppGeneratedContract(scope, app, apps, enableTailwind) {
4248
4536
  target: 'cloudflare',
4249
4537
  cloudflare: createCloudflareDeployContract(scope, app),
4250
4538
  worker: {
4539
+ compatibilityDate: CLOUDFLARE_COMPATIBILITY_DATE,
4251
4540
  name: createCloudflareWorkerName(scope, app),
4541
+ security: createCloudflareSecurityContract(),
4252
4542
  ssr: true
4253
4543
  },
4254
4544
  output: {
@@ -4293,8 +4583,12 @@ function createAppGeneratedContract(scope, app, apps, enableTailwind) {
4293
4583
  metadataExport: './src/routes/ultramodern-route-metadata',
4294
4584
  localisedUrls: createLocalisedUrlsMap(app),
4295
4585
  owned: createRouteOwnedI18nPaths(app),
4586
+ publicRoutes: createPublicRouteMetadata(app),
4587
+ privateByDefault: true,
4588
+ publicnessDefault: 'private-app-screen',
4296
4589
  generatedRouteMap: true,
4297
- manualOverrides: []
4590
+ manualOverrides: [],
4591
+ publicSurface: createPublicSurfaceContract(app)
4298
4592
  },
4299
4593
  moduleFederation: {
4300
4594
  name: app.mfName,
@@ -4770,6 +5064,7 @@ function createWorkspaceValidationScript(scope, enableTailwind, remotes = []) {
4770
5064
  const expectedBuildScript = remotes.length > 0 ? 'ULTRAMODERN_ZEPHYR=false pnpm -r --filter "./verticals/*" run build && ULTRAMODERN_ZEPHYR=false pnpm --filter "./apps/shell-super-app" run build && pnpm ultramodern:assert-mf-types' : 'ULTRAMODERN_ZEPHYR=false pnpm --filter "./apps/shell-super-app" run build && pnpm ultramodern:assert-mf-types';
4771
5065
  const expectedCloudflareBuildScript = remotes.length > 0 ? 'pnpm -r --filter "./verticals/*" run cloudflare:build && pnpm --filter "./apps/shell-super-app" run cloudflare:build && pnpm ultramodern:assert-mf-types' : 'pnpm --filter "./apps/shell-super-app" run cloudflare:build && pnpm ultramodern:assert-mf-types';
4772
5066
  const expectedCloudflareDeployScript = remotes.length > 0 ? 'pnpm -r --filter "./verticals/*" run cloudflare:deploy && pnpm --filter "./apps/shell-super-app" run cloudflare:deploy' : 'pnpm --filter "./apps/shell-super-app" run cloudflare:deploy';
5067
+ const expectedCloudflareSecurity = createCloudflareSecurityContract();
4773
5068
  return `import { execFileSync } from 'node:child_process';
4774
5069
  import fs from 'node:fs';
4775
5070
  import path from 'node:path';
@@ -4784,6 +5079,22 @@ const oldRemotePaths = ${JSON.stringify(oldRemotePaths, null, 2)};
4784
5079
  const expectedBuildScript = ${JSON.stringify(expectedBuildScript)};
4785
5080
  const expectedCloudflareBuildScript = ${JSON.stringify(expectedCloudflareBuildScript)};
4786
5081
  const expectedCloudflareDeployScript = ${JSON.stringify(expectedCloudflareDeployScript)};
5082
+ const expectedCloudflareSecurity = ${JSON.stringify(expectedCloudflareSecurity, null, 2)};
5083
+ const publicSurfaceRequiredAssetPaths = ${JSON.stringify([
5084
+ ...publicSurfaceRequiredAssetPaths
5085
+ ], null, 2)};
5086
+ const publicSurfaceOptionalAssetPaths = ${JSON.stringify([
5087
+ ...publicSurfaceOptionalAssetPaths
5088
+ ], null, 2)};
5089
+ const expectedModernPackageSpecifier = packageName => {
5090
+ if (packageSource.strategy === 'workspace') {
5091
+ return 'workspace:*';
5092
+ }
5093
+ const aliases = packageSource.modernPackages?.aliases ?? {};
5094
+ const alias = aliases[packageName];
5095
+ const specifier = packageSource.modernPackages?.specifier;
5096
+ return typeof alias === 'string' ? \`npm:\${alias}@\${specifier}\` : specifier;
5097
+ };
4787
5098
 
4788
5099
  const readText = relativePath => fs.readFileSync(path.join(root, relativePath), 'utf-8');
4789
5100
  const readJson = relativePath => JSON.parse(readText(relativePath));
@@ -4798,6 +5109,21 @@ const assertExists = relativePath => {
4798
5109
  const assertNotExists = relativePath => {
4799
5110
  assert(!fs.existsSync(path.join(root, relativePath)), \`Unexpected \${relativePath}\`);
4800
5111
  };
5112
+ const assertPublicSurfaceAssets = (appPath, publicRoutes) => {
5113
+ const robots = readText(\`\${appPath}/config/public/robots.txt\`);
5114
+ if ((publicRoutes ?? []).length === 0) {
5115
+ assert(robots.includes('Disallow: /'), \`\${appPath} robots.txt must disallow crawling when no public routes exist\`);
5116
+ for (const relativePath of publicSurfaceOptionalAssetPaths) {
5117
+ assertNotExists(\`\${appPath}/\${relativePath}\`);
5118
+ }
5119
+ return;
5120
+ }
5121
+ const sitemap = readText(\`\${appPath}/config/public/sitemap.xml\`);
5122
+ const manifest = readJson(\`\${appPath}/config/public/site.webmanifest\`);
5123
+ assert(!sitemap.includes('<lastmod>'), \`\${appPath} sitemap must omit build-time lastmod values\`);
5124
+ assert(typeof manifest.name === 'string' && manifest.name.length > 0, \`\${appPath} web manifest must include a safe app name\`);
5125
+ assert(typeof manifest.start_url === 'string' && manifest.start_url.startsWith('/'), \`\${appPath} web manifest start_url must be a public route path\`);
5126
+ };
4801
5127
  const expectedWorkerName = packageSuffix => \`\${packageScope}-\${packageSuffix}\`.slice(0, 63);
4802
5128
  const expectedChunkLoadingGlobal = mfName =>
4803
5129
  \`__ULTRAMODERN_\${mfName
@@ -4874,6 +5200,9 @@ const requiredPaths = [
4874
5200
  'apps/shell-super-app/src/routes/layout.tsx',
4875
5201
  'apps/shell-super-app/src/routes/ultramodern-route-metadata.ts',
4876
5202
  'apps/shell-super-app/src/routes/[lang]/page.tsx',
5203
+ ...publicSurfaceRequiredAssetPaths.map(
5204
+ relativePath => \`apps/shell-super-app/\${relativePath}\`,
5205
+ ),
4877
5206
  'packages/shared-contracts/src/index.ts',
4878
5207
  'packages/shared-design-tokens/src/index.ts',
4879
5208
  'packages/shared-design-tokens/src/tokens.css',
@@ -4900,6 +5229,9 @@ for (const vertical of fullStackVerticals) {
4900
5229
  \`\${vertical.path}/src/routes/layout.tsx\`,
4901
5230
  \`\${vertical.path}/src/routes/ultramodern-route-metadata.ts\`,
4902
5231
  \`\${vertical.path}/src/routes/[lang]/page.tsx\`,
5232
+ ...publicSurfaceRequiredAssetPaths.map(
5233
+ relativePath => \`\${vertical.path}/\${relativePath}\`,
5234
+ ),
4903
5235
  ...vertical.routePagePaths,
4904
5236
  );
4905
5237
  }
@@ -4934,6 +5266,31 @@ assert(rootPackage.modernjs?.preset === 'presetUltramodern', 'Root must declare
4934
5266
  assert(rootPackage.modernjs?.packageSource?.config === './.modernjs/ultramodern-package-source.json', 'Root must point at package source metadata');
4935
5267
  assert(rootPackage.modernjs?.packageSource?.strategy === packageSource.strategy, 'Root package source strategy must match metadata');
4936
5268
  assert(packageSource.strategy === 'workspace' || packageSource.strategy === 'install', 'Package source strategy must be workspace or install');
5269
+ assert(packageSource.strategy === 'install' || packageSource.modernPackages?.specifier === 'workspace:*', 'Workspace package source must be explicitly backed by workspace:*');
5270
+ if (packageSource.strategy === 'install') {
5271
+ const installSpecifier = packageSource.modernPackages?.specifier;
5272
+ assert(
5273
+ typeof installSpecifier === 'string' &&
5274
+ /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/.test(installSpecifier) &&
5275
+ installSpecifier.includes('ultramodern'),
5276
+ 'Install package source must use a semver UltraModern published cohort',
5277
+ );
5278
+ const modernAliases = packageSource.modernPackages?.aliases ?? {};
5279
+ if (Object.keys(modernAliases).length > 0) {
5280
+ for (const modernPackageName of [
5281
+ '@modern-js/app-tools',
5282
+ '@modern-js/plugin-bff',
5283
+ '@modern-js/plugin-i18n',
5284
+ '@modern-js/plugin-tanstack',
5285
+ '@modern-js/runtime',
5286
+ ]) {
5287
+ assert(
5288
+ /^@[^/]+\\/.+/.test(modernAliases[modernPackageName] ?? ''),
5289
+ \`Install package source alias for \${modernPackageName} must be a scoped npm package\`,
5290
+ );
5291
+ }
5292
+ }
5293
+ }
4937
5294
  assert(packageSource.generatedWorkspacePackages?.specifier === 'workspace:*', 'Generated workspace packages must keep workspace:* links');
4938
5295
  assert(
4939
5296
  rootPackage.scripts?.build === expectedBuildScript,
@@ -4950,6 +5307,7 @@ assert(rootPackage.scripts?.['skills:check'] === 'node ./scripts/bootstrap-agent
4950
5307
  assert(rootPackage.scripts?.postinstall === "oxfmt . '!repos/**' && node ./scripts/bootstrap-agent-skills.mjs && node ./scripts/setup-agent-reference-repos.mjs", 'Root postinstall must format, bootstrap agent skills, initialize git/hooks, and install reference repositories');
4951
5308
 
4952
5309
  const expectedAppIds = ['shell-super-app', ...fullStackVerticals.map(vertical => vertical.id)];
5310
+ const expectedCloudflareCompatibilityDate = '${CLOUDFLARE_COMPATIBILITY_DATE}';
4953
5311
  const expectedCloudflareCompatibilityFlags = ['nodejs_compat', 'global_fetch_strictly_public'];
4954
5312
  assert(
4955
5313
  JSON.stringify(generatedContract.apps?.map(app => app.id)) === JSON.stringify(expectedAppIds),
@@ -4966,6 +5324,7 @@ assert(generatedContract.cssFederation?.sharedDesignTokens?.dedupe?.duplicateBas
4966
5324
  assert(generatedContract.cssFederation?.sharedDesignTokens?.ssr?.firstPaintRequired === true, 'Shared design token CSS must be required for SSR first paint');
4967
5325
 
4968
5326
  const shellPackage = readJson('apps/shell-super-app/package.json');
5327
+ const shellModernConfig = readText('apps/shell-super-app/modern.config.ts');
4969
5328
  const expectedZephyrDependencies = Object.fromEntries(
4970
5329
  fullStackVerticals.map(vertical => [
4971
5330
  vertical.zephyrAlias,
@@ -4977,10 +5336,21 @@ assert(
4977
5336
  JSON.stringify(expectedZephyrDependencies),
4978
5337
  'Shell Zephyr dependencies must reference every vertical package',
4979
5338
  );
5339
+ assert(shellPackage.devDependencies?.['@modern-js/app-tools'] === expectedModernPackageSpecifier('@modern-js/app-tools'), 'Shell app-tools dependency must match package source metadata');
5340
+ assert(shellPackage.dependencies?.['@modern-js/plugin-bff'] === expectedModernPackageSpecifier('@modern-js/plugin-bff'), 'Shell plugin-bff dependency must match package source metadata');
5341
+ assert(shellPackage.dependencies?.['@modern-js/plugin-i18n'] === expectedModernPackageSpecifier('@modern-js/plugin-i18n'), 'Shell plugin-i18n dependency must match package source metadata');
5342
+ assert(shellPackage.dependencies?.['@modern-js/plugin-tanstack'] === expectedModernPackageSpecifier('@modern-js/plugin-tanstack'), 'Shell plugin-tanstack dependency must match package source metadata');
5343
+ assert(shellPackage.dependencies?.['@modern-js/runtime'] === expectedModernPackageSpecifier('@modern-js/runtime'), 'Shell runtime dependency must match package source metadata');
4980
5344
  const shellContract = generatedContract.apps?.find(app => app.id === 'shell-super-app');
4981
5345
  assert(shellContract?.deploy?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell Cloudflare workerName is incorrect');
4982
5346
  assert(shellContract?.deploy?.cloudflare?.publicUrlEnv === 'ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP', 'Shell Cloudflare public URL env is incorrect');
5347
+ assert(shellContract?.deploy?.cloudflare?.compatibilityDate === expectedCloudflareCompatibilityDate, 'Shell Cloudflare compatibilityDate is incorrect');
4983
5348
  assert(JSON.stringify(shellContract?.deploy?.cloudflare?.compatibilityFlags) === JSON.stringify(expectedCloudflareCompatibilityFlags), 'Shell Cloudflare compatibility flags are incorrect');
5349
+ assert(JSON.stringify(shellContract?.deploy?.cloudflare?.security) === JSON.stringify(expectedCloudflareSecurity), 'Shell Cloudflare security contract is incorrect');
5350
+ assert(shellContract?.deploy?.worker?.compatibilityDate === expectedCloudflareCompatibilityDate, 'Shell worker compatibilityDate is incorrect');
5351
+ assert(shellContract?.deploy?.worker?.name === expectedWorkerName('shell-super-app'), 'Shell worker name is incorrect');
5352
+ assert(shellModernConfig.includes("const cloudflareWorkerName = '" + expectedWorkerName('shell-super-app') + "'"), 'Shell modern.config.ts must define the Cloudflare worker name');
5353
+ assert(shellModernConfig.includes('name: cloudflareWorkerName'), 'Shell modern.config.ts must wire deploy.worker.name');
4984
5354
  assert(shellContract?.config?.rspack?.output?.uniqueName === 'shellSuperApp', 'Shell Rspack uniqueName is incorrect');
4985
5355
  assert(shellContract?.config?.rspack?.output?.chunkLoadingGlobal === expectedChunkLoadingGlobal('shellSuperApp'), 'Shell Rspack chunkLoadingGlobal is incorrect');
4986
5356
  assert(topology.shell?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell topology Cloudflare workerName is incorrect');
@@ -4994,6 +5364,14 @@ assert(shellContract?.styling?.federation?.entrypoints?.css?.includes('src/route
4994
5364
  assert(shellContract?.styling?.federation?.assets?.shared?.some(asset => asset.endsWith('/shared-design-tokens/tokens.css')), 'Shell must import the shared design token CSS asset');
4995
5365
  assert(shellContract?.styling?.federation?.dedupe?.duplicateBaseStylesAllowed === false, 'Shell CSS contract must forbid duplicated base styles');
4996
5366
  assert(shellContract?.styling?.federation?.ssr?.firstPaintRequired === true, 'Shell CSS must be required for SSR first paint');
5367
+ assert(shellContract?.routes?.privateByDefault === true, 'Shell routes must be private by default');
5368
+ assert(shellContract?.routes?.publicnessDefault === 'private-app-screen', 'Shell route publicness default is incorrect');
5369
+ assert(JSON.stringify(shellContract?.routes?.publicRoutes ?? []) === '[]', 'Shell must not expose generated public routes by default');
5370
+ assert(
5371
+ (shellContract?.routes?.owned ?? []).every(route => route.public === false && route.indexable === false && route.publicSurface === 'private-app-screen'),
5372
+ 'Shell owned routes must be non-indexable private app screens by default',
5373
+ );
5374
+ assertPublicSurfaceAssets('apps/shell-super-app', shellContract?.routes?.publicRoutes ?? []);
4997
5375
  assert(
4998
5376
  topology.shell?.verticalRefs?.join(',') === fullStackVerticals.map(vertical => vertical.id).join(','),
4999
5377
  'Topology shell verticalRefs must match generated verticals',
@@ -5004,10 +5382,15 @@ assert(!('effectServices' in topology), 'Default APIs must be vertical-owned, no
5004
5382
 
5005
5383
  for (const vertical of fullStackVerticals) {
5006
5384
  const packageJson = readJson(\`\${vertical.path}/package.json\`);
5385
+ const modernConfig = readText(\`\${vertical.path}/modern.config.ts\`);
5007
5386
  assert(packageJson.name === vertical.packageName, \`\${vertical.id} package name is incorrect\`);
5008
5387
  assert(packageJson.scripts?.['cloudflare:deploy'] === 'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS=true pnpm run cloudflare:build && wrangler deploy --config .output/wrangler.json', \`\${vertical.id} must expose cloudflare:deploy\`);
5009
5388
  assert(packageJson.scripts?.['cloudflare:proof']?.includes(\`--app \${vertical.id}\`), \`\${vertical.id} must expose cloudflare:proof\`);
5010
- assert(packageJson.dependencies?.['@modern-js/plugin-bff'], \`\${vertical.id} must depend on plugin-bff\`);
5389
+ assert(packageJson.devDependencies?.['@modern-js/app-tools'] === expectedModernPackageSpecifier('@modern-js/app-tools'), \`\${vertical.id} app-tools dependency must match package source metadata\`);
5390
+ assert(packageJson.dependencies?.['@modern-js/plugin-bff'] === expectedModernPackageSpecifier('@modern-js/plugin-bff'), \`\${vertical.id} plugin-bff dependency must match package source metadata\`);
5391
+ assert(packageJson.dependencies?.['@modern-js/plugin-i18n'] === expectedModernPackageSpecifier('@modern-js/plugin-i18n'), \`\${vertical.id} plugin-i18n dependency must match package source metadata\`);
5392
+ assert(packageJson.dependencies?.['@modern-js/plugin-tanstack'] === expectedModernPackageSpecifier('@modern-js/plugin-tanstack'), \`\${vertical.id} plugin-tanstack dependency must match package source metadata\`);
5393
+ assert(packageJson.dependencies?.['@modern-js/runtime'] === expectedModernPackageSpecifier('@modern-js/runtime'), \`\${vertical.id} runtime dependency must match package source metadata\`);
5011
5394
  assert(packageJson.exports?.['./effect/client'] === \`./src/effect/\${vertical.stem}-client.ts\`, \`\${vertical.id} must export its Effect client\`);
5012
5395
  assert(packageJson.exports?.['./shared/effect/api'] === './shared/effect/api.ts', \`\${vertical.id} must export its Effect API contract\`);
5013
5396
  const expectedVerticalZephyrDependencies = Object.fromEntries(
@@ -5029,7 +5412,13 @@ for (const vertical of fullStackVerticals) {
5029
5412
  assert(contractEntry?.kind === 'vertical', \`\${vertical.id} generated contract kind is incorrect\`);
5030
5413
  assert(contractEntry?.deploy?.cloudflare?.workerName === expectedWorkerName(vertical.id), \`\${vertical.id} Cloudflare workerName is incorrect\`);
5031
5414
  assert(contractEntry?.deploy?.cloudflare?.publicUrlEnv === \`ULTRAMODERN_PUBLIC_URL_\${vertical.id.replace(/-/g, '_').toUpperCase()}\`, \`\${vertical.id} Cloudflare public URL env is incorrect\`);
5415
+ assert(contractEntry?.deploy?.cloudflare?.compatibilityDate === expectedCloudflareCompatibilityDate, \`\${vertical.id} Cloudflare compatibilityDate is incorrect\`);
5032
5416
  assert(JSON.stringify(contractEntry?.deploy?.cloudflare?.compatibilityFlags) === JSON.stringify(expectedCloudflareCompatibilityFlags), \`\${vertical.id} Cloudflare compatibility flags are incorrect\`);
5417
+ assert(JSON.stringify(contractEntry?.deploy?.cloudflare?.security) === JSON.stringify(expectedCloudflareSecurity), \`\${vertical.id} Cloudflare security contract is incorrect\`);
5418
+ assert(contractEntry?.deploy?.worker?.compatibilityDate === expectedCloudflareCompatibilityDate, \`\${vertical.id} worker compatibilityDate is incorrect\`);
5419
+ assert(contractEntry?.deploy?.worker?.name === expectedWorkerName(vertical.id), \`\${vertical.id} worker name is incorrect\`);
5420
+ assert(modernConfig.includes("const cloudflareWorkerName = '" + expectedWorkerName(vertical.id) + "'"), \`\${vertical.id} modern.config.ts must define the Cloudflare worker name\`);
5421
+ assert(modernConfig.includes('name: cloudflareWorkerName'), \`\${vertical.id} modern.config.ts must wire deploy.worker.name\`);
5033
5422
  assert(contractEntry?.deploy?.cloudflare?.routes?.effectReadiness === \`\${vertical.apiPrefix}/effect/\${vertical.stem}/readiness\`, \`\${vertical.id} Cloudflare proof readiness route is incorrect\`);
5034
5423
  assert(contractEntry?.config?.rspack?.output?.uniqueName === vertical.mfName, \`\${vertical.id} Rspack uniqueName is incorrect\`);
5035
5424
  assert(contractEntry?.config?.rspack?.output?.chunkLoadingGlobal === expectedChunkLoadingGlobal(vertical.mfName), \`\${vertical.id} Rspack chunkLoadingGlobal is incorrect\`);
@@ -5056,6 +5445,14 @@ for (const vertical of fullStackVerticals) {
5056
5445
  );
5057
5446
  assert(contractEntry?.routes?.source === 'route-owned', \`\${vertical.id} routes must be route-owned\`);
5058
5447
  assert(contractEntry?.routes?.metadataExport === './src/routes/ultramodern-route-metadata', \`\${vertical.id} route metadata export is incorrect\`);
5448
+ assert(contractEntry?.routes?.privateByDefault === true, \`\${vertical.id} routes must be private by default\`);
5449
+ assert(contractEntry?.routes?.publicnessDefault === 'private-app-screen', \`\${vertical.id} route publicness default is incorrect\`);
5450
+ assert(JSON.stringify(contractEntry?.routes?.publicRoutes ?? []) === '[]', \`\${vertical.id} must not expose generated public routes by default\`);
5451
+ assert(
5452
+ (contractEntry?.routes?.owned ?? []).every(route => route.public === false && route.indexable === false && route.publicSurface === 'private-app-screen'),
5453
+ \`\${vertical.id} owned routes must be non-indexable private app screens by default\`,
5454
+ );
5455
+ assertPublicSurfaceAssets(vertical.path, contractEntry?.routes?.publicRoutes ?? []);
5059
5456
  assert(contractEntry?.styling?.federation?.owner?.id === vertical.id, \`\${vertical.id} CSS federation owner is missing\`);
5060
5457
  assert(contractEntry?.styling?.federation?.role === 'vertical-css', \`\${vertical.id} must own only vertical CSS\`);
5061
5458
  assert(contractEntry?.styling?.federation?.rootSelector === \`[data-app-id="\${vertical.id}"]\`, \`\${vertical.id} CSS root selector is incorrect\`);
@@ -5161,8 +5558,14 @@ async function fetchText(url) {
5161
5558
  ok: response.ok,
5162
5559
  status: response.status,
5163
5560
  accessControlAllowOrigin: response.headers.get('access-control-allow-origin'),
5561
+ contentSecurityPolicy: response.headers.get('content-security-policy'),
5562
+ contentSecurityPolicyReportOnly: response.headers.get('content-security-policy-report-only'),
5164
5563
  contentType: response.headers.get('content-type'),
5165
5564
  link: response.headers.get('link'),
5565
+ permissionsPolicy: response.headers.get('permissions-policy'),
5566
+ referrerPolicy: response.headers.get('referrer-policy'),
5567
+ xContentTypeOptions: response.headers.get('x-content-type-options'),
5568
+ xRobotsTag: response.headers.get('x-robots-tag'),
5166
5569
  body: await response.text(),
5167
5570
  };
5168
5571
  }
@@ -5213,6 +5616,139 @@ function assert(condition, message) {
5213
5616
  }
5214
5617
  }
5215
5618
 
5619
+ function matchesPreviewHostname(hostname, pattern) {
5620
+ const normalizedHostname = hostname.toLowerCase();
5621
+ const normalizedPattern = String(pattern || '').toLowerCase();
5622
+
5623
+ if (!normalizedPattern) {
5624
+ return false;
5625
+ }
5626
+
5627
+ if (normalizedPattern.startsWith('*.')) {
5628
+ return normalizedHostname.endsWith(normalizedPattern.slice(1));
5629
+ }
5630
+
5631
+ return normalizedHostname === normalizedPattern;
5632
+ }
5633
+
5634
+ function shouldNoindexUrl(publicUrl, noindex) {
5635
+ if (!noindex || noindex === false) {
5636
+ return false;
5637
+ }
5638
+
5639
+ const { hostname } = new URL(publicUrl);
5640
+ const normalizedHostname = hostname.toLowerCase();
5641
+
5642
+ if (
5643
+ noindex.localhost !== false &&
5644
+ (normalizedHostname === 'localhost' ||
5645
+ normalizedHostname === '127.0.0.1' ||
5646
+ normalizedHostname === '[::1]')
5647
+ ) {
5648
+ return true;
5649
+ }
5650
+
5651
+ if (
5652
+ noindex.workersDev !== false &&
5653
+ normalizedHostname.endsWith('.workers.dev')
5654
+ ) {
5655
+ return true;
5656
+ }
5657
+
5658
+ return (noindex.previewHostnames || []).some(pattern =>
5659
+ matchesPreviewHostname(normalizedHostname, pattern),
5660
+ );
5661
+ }
5662
+
5663
+ function assertHeader(evidence, response, expected, options) {
5664
+ if (expected === false || expected === undefined) {
5665
+ return;
5666
+ }
5667
+
5668
+ const actual = response[options.field];
5669
+ evidence.assertions.push({
5670
+ type: 'security-header',
5671
+ header: options.header,
5672
+ route: options.route,
5673
+ expected,
5674
+ actual,
5675
+ status: actual === expected ? 'pass' : 'fail',
5676
+ });
5677
+ assert(actual === expected, \`\${options.appId} \${options.route} is missing \${options.header}\`);
5678
+ }
5679
+
5680
+ function assertCloudflareSecurity(evidence, app, response, route, publicUrl, options = {}) {
5681
+ const security = app.deploy?.cloudflare?.security;
5682
+
5683
+ if (!security || security.enabled === false) {
5684
+ return;
5685
+ }
5686
+
5687
+ const headers = security.headers || {};
5688
+ assertHeader(evidence, response, headers.referrerPolicy, {
5689
+ appId: app.id,
5690
+ field: 'referrerPolicy',
5691
+ header: 'referrer-policy',
5692
+ route,
5693
+ });
5694
+ assertHeader(evidence, response, headers.contentTypeOptions, {
5695
+ appId: app.id,
5696
+ field: 'xContentTypeOptions',
5697
+ header: 'x-content-type-options',
5698
+ route,
5699
+ });
5700
+ assertHeader(evidence, response, headers.permissionsPolicy, {
5701
+ appId: app.id,
5702
+ field: 'permissionsPolicy',
5703
+ header: 'permissions-policy',
5704
+ route,
5705
+ });
5706
+
5707
+ const csp = security.contentSecurityPolicy;
5708
+ if (options.html && csp?.mode !== 'off') {
5709
+ const header =
5710
+ csp?.mode === 'enforce'
5711
+ ? 'content-security-policy'
5712
+ : 'content-security-policy-report-only';
5713
+ const actual =
5714
+ csp?.mode === 'enforce'
5715
+ ? response.contentSecurityPolicy
5716
+ : response.contentSecurityPolicyReportOnly;
5717
+ const expectedDirectives = ['script-src', 'style-src', 'connect-src'];
5718
+ const missingDirectives = expectedDirectives.filter(
5719
+ directive => !actual?.includes(directive),
5720
+ );
5721
+
5722
+ evidence.assertions.push({
5723
+ type: 'security-csp',
5724
+ header,
5725
+ route,
5726
+ mode: csp?.mode ?? 'report-only',
5727
+ actual,
5728
+ missingDirectives,
5729
+ status: actual && missingDirectives.length === 0 ? 'pass' : 'fail',
5730
+ });
5731
+ assert(actual, \`\${app.id} \${route} is missing \${header}\`);
5732
+ assert(
5733
+ missingDirectives.length === 0,
5734
+ \`\${app.id} \${route} CSP is missing \${missingDirectives.join(', ')}\`,
5735
+ );
5736
+ }
5737
+
5738
+ if (shouldNoindexUrl(publicUrl, security.noindex)) {
5739
+ evidence.assertions.push({
5740
+ type: 'security-noindex',
5741
+ route,
5742
+ actual: response.xRobotsTag,
5743
+ status: response.xRobotsTag === 'noindex, nofollow' ? 'pass' : 'fail',
5744
+ });
5745
+ assert(
5746
+ response.xRobotsTag === 'noindex, nofollow',
5747
+ \`\${app.id} \${route} is missing noindex X-Robots-Tag\`,
5748
+ );
5749
+ }
5750
+ }
5751
+
5216
5752
  async function validateApp(app, publicUrl) {
5217
5753
  const cloudflare = app.deploy?.cloudflare;
5218
5754
  const routes = cloudflare?.routes ?? {};
@@ -5233,6 +5769,9 @@ async function validateApp(app, publicUrl) {
5233
5769
  statusCode: ssr.status,
5234
5770
  });
5235
5771
  assert(ssr.ok, \`\${app.id} SSR route returned HTTP \${ssr.status}\`);
5772
+ assertCloudflareSecurity(evidence, app, ssr, ssrRoute, publicUrl, {
5773
+ html: true,
5774
+ });
5236
5775
 
5237
5776
  const uiMarker = extractUiMarker(ssr.body);
5238
5777
  evidence.assertions.push({
@@ -5286,6 +5825,7 @@ async function validateApp(app, publicUrl) {
5286
5825
  manifest.ok,
5287
5826
  \`\${app.id} MF manifest returned HTTP \${manifest.status}\`,
5288
5827
  );
5828
+ assertCloudflareSecurity(evidence, app, manifest, manifestRoute, publicUrl);
5289
5829
  evidence.assertions.push({
5290
5830
  type: 'mf-manifest-cors',
5291
5831
  route: manifestRoute,
@@ -5325,6 +5865,7 @@ async function validateApp(app, publicUrl) {
5325
5865
  statusCode: locale.status,
5326
5866
  });
5327
5867
  assert(locale.ok, \`\${app.id} locale JSON returned HTTP \${locale.status}\`);
5868
+ assertCloudflareSecurity(evidence, app, locale, localeRoute, publicUrl);
5328
5869
  evidence.assertions.push({
5329
5870
  type: 'i18n-cors',
5330
5871
  route: localeRoute,
@@ -5570,6 +6111,7 @@ function rewriteShellAppFiles(workspaceRoot, scope, packageSource, enableTailwin
5570
6111
  writeJsonFile(node_path.join(workspaceRoot, `${shellApp.directory}/package.json`), createAppPackage(scope, shellHost, packageSource, enableTailwind, remotes));
5571
6112
  writeFileReplacing(workspaceRoot, `${shellApp.directory}/src/modern-app-env.d.ts`, createAppEnvDts(shellHost, remotes));
5572
6113
  writeFileReplacing(workspaceRoot, `${shellApp.directory}/src/routes/ultramodern-route-metadata.ts`, createRouteMetadataModule(shellHost));
6114
+ rewriteWorkspaceAssetsForApp(workspaceRoot, shellHost);
5573
6115
  writeFileReplacing(workspaceRoot, `${shellApp.directory}/src/modern.runtime.ts`, createAppRuntimeConfig(shellHost, scope, remotes));
5574
6116
  writeJsonFile(node_path.join(workspaceRoot, `${shellApp.directory}/locales/en/translation.json`), createAppPublicLocaleMessages(shellHost, 'en', remotes));
5575
6117
  writeJsonFile(node_path.join(workspaceRoot, `${shellApp.directory}/locales/en/${appI18nNamespace(shellHost)}.json`), createAppPublicLocaleMessages(shellHost, 'en', remotes));
@@ -6138,7 +6680,7 @@ function readCreatePackageJson() {
6138
6680
  return JSON.parse(node_fs.readFileSync(createPackageJson, 'utf-8'));
6139
6681
  }
6140
6682
  function isBleedingDevCreatePackage(createPackage) {
6141
- return '@bleedingdev/modern-js-create' === createPackage.name;
6683
+ return createPackage.name === BLEEDINGDEV_CREATE_PACKAGE;
6142
6684
  }
6143
6685
  function getBleedingDevFrameworkVersion(createPackage, fallbackVersion) {
6144
6686
  const frameworkVersion = createPackage.ultramodern?.frameworkVersion;
@@ -6245,71 +6787,109 @@ function detectUltramodernPackageSource(args, defaultPackageVersion, createPacka
6245
6787
  console.error('--ultramodern-package-source must be "workspace" or "install"');
6246
6788
  process.exit(1);
6247
6789
  }
6790
+ const packageSourceStrategy = strategy;
6791
+ const explicitRegistry = getOptionValue(args, [
6792
+ '--ultramodern-package-registry'
6793
+ ]);
6794
+ const aliasScope = getOptionValue(args, [
6795
+ '--ultramodern-package-scope'
6796
+ ]) ?? (bleedingDevDefaults && 'install' === packageSourceStrategy && !explicitRegistry ? BLEEDINGDEV_PACKAGE_SCOPE : void 0);
6248
6797
  return {
6249
- strategy,
6798
+ strategy: packageSourceStrategy,
6250
6799
  modernPackageVersion: getOptionValue(args, [
6251
6800
  '--ultramodern-package-version'
6252
6801
  ]) ?? defaultPackageVersion,
6253
- registry: getOptionValue(args, [
6254
- '--ultramodern-package-registry'
6255
- ]),
6256
- aliasScope: getOptionValue(args, [
6257
- '--ultramodern-package-scope'
6258
- ]) ?? (bleedingDevDefaults && 'install' === strategy ? 'bleedingdev' : void 0),
6802
+ registry: explicitRegistry,
6803
+ aliasScope,
6259
6804
  aliasPackageNamePrefix: getOptionValue(args, [
6260
6805
  '--ultramodern-package-name-prefix'
6261
- ]) ?? 'modern-js-'
6806
+ ]) ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
6262
6807
  };
6263
6808
  }
6264
- function src_modernAliasPackageName(packageName, packageSource) {
6265
- if (!packageSource.aliasScope) return packageName;
6266
- const scope = packageSource.aliasScope.replace(/^@/, '');
6267
- const unscopedName = packageName.split('/').at(-1);
6268
- return `@${scope}/${packageSource.aliasPackageNamePrefix ?? ''}${unscopedName}`;
6809
+ function hasExplicitUltramodernPackageSource(args, value) {
6810
+ const configuredValue = getOptionValue(args, [
6811
+ '--ultramodern-package-source'
6812
+ ]);
6813
+ return value ? configuredValue === value : void 0 !== configuredValue;
6269
6814
  }
6270
- function singleAppModernPackageSpecifier(packageName, packageSource, useWorkspaceProtocol) {
6271
- if (useWorkspaceProtocol) return 'workspace:*';
6272
- if ('install' !== packageSource.strategy || !packageSource.aliasScope) return packageSource.modernPackageVersion;
6273
- return `npm:${src_modernAliasPackageName(packageName, packageSource)}@${packageSource.modernPackageVersion}`;
6815
+ function readBleedingDevFrameworkVersionFromRegistry() {
6816
+ const envVersion = process.env[BLEEDINGDEV_FRAMEWORK_VERSION_ENV]?.trim();
6817
+ if (envVersion) {
6818
+ if (!semverPattern.test(envVersion)) {
6819
+ console.error(`${BLEEDINGDEV_FRAMEWORK_VERSION_ENV} must be a valid semver version`);
6820
+ process.exit(1);
6821
+ }
6822
+ return envVersion;
6823
+ }
6824
+ try {
6825
+ const rawVersion = runSetupCommand('npm', [
6826
+ 'view',
6827
+ `${BLEEDINGDEV_CREATE_PACKAGE}@latest`,
6828
+ 'ultramodern.frameworkVersion',
6829
+ '--json'
6830
+ ]).trim();
6831
+ const version = JSON.parse(rawVersion);
6832
+ if ('string' == typeof version && semverPattern.test(version)) return version;
6833
+ } catch {}
6834
+ console.error([
6835
+ `Could not resolve ${BLEEDINGDEV_CREATE_PACKAGE}@latest ultramodern.frameworkVersion.`,
6836
+ 'Pass --workspace to use local workspace protocol dependencies,',
6837
+ 'or pass --ultramodern-package-version with the exact BleedingDev framework cohort.'
6838
+ ].join(' '));
6839
+ process.exit(1);
6274
6840
  }
6275
- const singleAppModernPackages = [
6276
- '@modern-js/runtime',
6277
- '@modern-js/app-tools',
6278
- '@modern-js/tsconfig',
6279
- '@modern-js/plugin-i18n',
6280
- '@modern-js/plugin-tanstack',
6281
- '@modern-js/plugin-bff',
6282
- '@modern-js/adapter-rstest'
6283
- ];
6284
- function createSingleAppPackageSourceEvidence(packageSource, useWorkspaceProtocol) {
6285
- const strategy = useWorkspaceProtocol ? 'workspace' : 'install';
6286
- const specifier = useWorkspaceProtocol ? 'workspace:*' : packageSource.modernPackageVersion;
6287
- const aliases = 'install' === strategy && packageSource.aliasScope ? Object.fromEntries(singleAppModernPackages.map((packageName)=>[
6288
- packageName,
6289
- src_modernAliasPackageName(packageName, packageSource)
6290
- ])) : void 0;
6841
+ function resolveInstallBackedPackageSource(args, createPackage, packageSource) {
6842
+ const explicitVersion = getOptionValue(args, [
6843
+ '--ultramodern-package-version'
6844
+ ]);
6845
+ const explicitRegistry = getOptionValue(args, [
6846
+ '--ultramodern-package-registry'
6847
+ ]);
6848
+ const aliasScope = getOptionValue(args, [
6849
+ '--ultramodern-package-scope'
6850
+ ]) ?? packageSource.aliasScope ?? (explicitRegistry ? void 0 : BLEEDINGDEV_PACKAGE_SCOPE);
6851
+ return {
6852
+ ...packageSource,
6853
+ strategy: 'install',
6854
+ modernPackageVersion: explicitVersion ?? (isBleedingDevCreatePackage(createPackage) ? packageSource.modernPackageVersion : readBleedingDevFrameworkVersionFromRegistry()),
6855
+ aliasScope,
6856
+ aliasPackageNamePrefix: getOptionValue(args, [
6857
+ '--ultramodern-package-name-prefix'
6858
+ ]) ?? packageSource.aliasPackageNamePrefix ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
6859
+ };
6860
+ }
6861
+ function resolveSingleAppPackageSource(args, createPackage, packageSource, useWorkspaceProtocol) {
6862
+ if (useWorkspaceProtocol) return {
6863
+ ...packageSource,
6864
+ strategy: 'workspace',
6865
+ modernPackageVersion: WORKSPACE_PACKAGE_VERSION
6866
+ };
6867
+ return resolveInstallBackedPackageSource(args, createPackage, packageSource);
6868
+ }
6869
+ function resolveWorkspacePackageSource(args, createPackage, packageSource) {
6870
+ if (hasExplicitUltramodernPackageSource(args, 'workspace')) return {
6871
+ ...packageSource,
6872
+ strategy: 'workspace',
6873
+ modernPackageVersion: WORKSPACE_PACKAGE_VERSION
6874
+ };
6875
+ return resolveInstallBackedPackageSource(args, createPackage, packageSource);
6876
+ }
6877
+ function createSingleAppPackageSourceEvidence(packageSource) {
6291
6878
  return {
6292
6879
  schemaVersion: 1,
6293
6880
  preset: 'presetUltramodern',
6294
- strategy,
6295
- modernPackages: {
6296
- specifier,
6297
- packages: singleAppModernPackages,
6298
- ...packageSource.registry ? {
6299
- registry: packageSource.registry
6300
- } : {},
6301
- ...aliases ? {
6302
- aliases
6303
- } : {}
6304
- }
6881
+ strategy: packageSource.strategy,
6882
+ modernPackages: createModernPackagesMetadata(ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES, packageSource, {
6883
+ includeAliases: 'install' === packageSource.strategy
6884
+ })
6305
6885
  };
6306
6886
  }
6307
- function writeSingleAppPackageSourceEvidence(targetDir, packageSource, useWorkspaceProtocol) {
6887
+ function writeSingleAppPackageSourceEvidence(targetDir, packageSource) {
6308
6888
  const evidencePath = node_path.join(targetDir, '.modernjs', 'ultramodern-package-source.json');
6309
6889
  node_fs.mkdirSync(node_path.dirname(evidencePath), {
6310
6890
  recursive: true
6311
6891
  });
6312
- node_fs.writeFileSync(evidencePath, `${JSON.stringify(createSingleAppPackageSourceEvidence(packageSource, useWorkspaceProtocol), null, 2)}\n`);
6892
+ node_fs.writeFileSync(evidencePath, `${JSON.stringify(createSingleAppPackageSourceEvidence(packageSource), null, 2)}\n`);
6313
6893
  }
6314
6894
  function runSetupCommand(command, args, options = {}) {
6315
6895
  return execFileSync(command, args, {
@@ -6514,12 +7094,13 @@ async function main() {
6514
7094
  }
6515
7095
  const generateWorkspace = detectUltramodernWorkspaceFlag();
6516
7096
  if (generateWorkspace) {
7097
+ const packageSource = resolveWorkspacePackageSource(args, createPackage, detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage));
6517
7098
  generateUltramodernWorkspace({
6518
7099
  targetDir,
6519
7100
  packageName: generatedPackageName,
6520
7101
  modernVersion: version,
6521
7102
  enableTailwind: detectTailwindFlag(),
6522
- packageSource: detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage)
7103
+ packageSource
6523
7104
  });
6524
7105
  initializeGeneratedGitRepository(targetDir);
6525
7106
  const dim = '\x1b[2m\x1b[3m';
@@ -6540,19 +7121,19 @@ async function main() {
6540
7121
  const bffRuntime = detectBffRuntime();
6541
7122
  const enableTailwind = detectTailwindFlag();
6542
7123
  const useWorkspaceProtocol = detectWorkspaceProtocolFlag();
6543
- const packageSource = detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage);
6544
- const templateManifest = createBuiltinTemplateManifest(version);
7124
+ const packageSource = resolveSingleAppPackageSource(args, createPackage, detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage), useWorkspaceProtocol);
7125
+ const templateManifest = createBuiltinTemplateManifest('install' === packageSource.strategy ? packageSource.modernPackageVersion : version);
6545
7126
  validateTemplateManifest(templateManifest);
6546
7127
  copyTemplate(templateDir, targetDir, {
6547
7128
  packageName: generatedPackageName,
6548
- version: useWorkspaceProtocol ? 'workspace:*' : packageSource.modernPackageVersion,
6549
- runtimeVersion: singleAppModernPackageSpecifier('@modern-js/runtime', packageSource, useWorkspaceProtocol),
6550
- appToolsVersion: singleAppModernPackageSpecifier('@modern-js/app-tools', packageSource, useWorkspaceProtocol),
6551
- adapterRstestVersion: singleAppModernPackageSpecifier('@modern-js/adapter-rstest', packageSource, useWorkspaceProtocol),
6552
- tsconfigVersion: singleAppModernPackageSpecifier('@modern-js/tsconfig', packageSource, useWorkspaceProtocol),
6553
- pluginTanstackVersion: singleAppModernPackageSpecifier('@modern-js/plugin-tanstack', packageSource, useWorkspaceProtocol),
6554
- pluginBffVersion: singleAppModernPackageSpecifier('@modern-js/plugin-bff', packageSource, useWorkspaceProtocol),
6555
- pluginI18nVersion: singleAppModernPackageSpecifier('@modern-js/plugin-i18n', packageSource, useWorkspaceProtocol),
7129
+ version: 'workspace' === packageSource.strategy ? WORKSPACE_PACKAGE_VERSION : packageSource.modernPackageVersion,
7130
+ runtimeVersion: modernPackageSpecifier('@modern-js/runtime', packageSource),
7131
+ appToolsVersion: modernPackageSpecifier('@modern-js/app-tools', packageSource),
7132
+ adapterRstestVersion: modernPackageSpecifier('@modern-js/adapter-rstest', packageSource),
7133
+ tsconfigVersion: modernPackageSpecifier('@modern-js/tsconfig', packageSource),
7134
+ pluginTanstackVersion: modernPackageSpecifier('@modern-js/plugin-tanstack', packageSource),
7135
+ pluginBffVersion: modernPackageSpecifier('@modern-js/plugin-bff', packageSource),
7136
+ pluginI18nVersion: modernPackageSpecifier('@modern-js/plugin-i18n', packageSource),
6556
7137
  tanstackRouterVersion: src_TANSTACK_ROUTER_VERSION,
6557
7138
  tailwindVersion: src_TAILWIND_VERSION,
6558
7139
  tailwindPostcssVersion: src_TAILWIND_POSTCSS_VERSION,
@@ -6570,7 +7151,7 @@ async function main() {
6570
7151
  ...packageJson.modernjs ?? {},
6571
7152
  preset: 'presetUltramodern',
6572
7153
  packageSource: {
6573
- strategy: useWorkspaceProtocol ? 'workspace' : 'install',
7154
+ strategy: packageSource.strategy,
6574
7155
  config: './.modernjs/ultramodern-package-source.json'
6575
7156
  }
6576
7157
  };
@@ -6605,7 +7186,7 @@ async function main() {
6605
7186
  }
6606
7187
  node_fs.writeFileSync(targetPackageJson, `${JSON.stringify(packageJson, null, 2)}\n`);
6607
7188
  writeTemplateManifestEvidence(targetDir, templateManifest);
6608
- writeSingleAppPackageSourceEvidence(targetDir, packageSource, useWorkspaceProtocol);
7189
+ writeSingleAppPackageSourceEvidence(targetDir, packageSource);
6609
7190
  if (!isSubproject) initializeGeneratedGitRepository(targetDir);
6610
7191
  const dim = '\x1b[2m\x1b[3m';
6611
7192
  const reset = '\x1b[0m';