@bleedingdev/modern-js-create 3.2.0-ultramodern.103 → 3.2.0-ultramodern.105

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,29 +559,87 @@ 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
- const TANSTACK_ROUTER_VERSION = '1.170.11';
565
- const MODULE_FEDERATION_VERSION = '2.5.0';
622
+ const TANSTACK_ROUTER_VERSION = '1.170.15';
623
+ const MODULE_FEDERATION_VERSION = '2.5.1';
566
624
  const ZEPHYR_RSPACK_PLUGIN_VERSION = '1.1.1';
567
625
  const ZEPHYR_AGENT_VERSION = '1.1.1';
568
- const WRANGLER_VERSION = '4.95.0';
626
+ const WRANGLER_VERSION = '4.98.0';
569
627
  const CLOUDFLARE_COMPATIBILITY_DATE = '2026-06-02';
570
628
  const TAILWIND_VERSION = '4.3.0';
571
629
  const TAILWIND_POSTCSS_VERSION = '4.3.0';
572
- const EFFECT_TSGO_VERSION = '0.13.0';
630
+ const POSTCSS_VERSION = '8.5.15';
631
+ const EFFECT_TSGO_VERSION = '0.14.0';
573
632
  const TYPESCRIPT_VERSION = '6.0.3';
574
- const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260527.2';
575
- const OXLINT_VERSION = '1.66.0';
576
- const OXFMT_VERSION = '0.51.0';
577
- const ULTRACITE_VERSION = '7.7.0';
633
+ const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260606.1';
634
+ const OXLINT_VERSION = '1.68.0';
635
+ const OXFMT_VERSION = '0.53.0';
636
+ const ULTRACITE_VERSION = '7.8.1';
578
637
  const LEFTHOOK_VERSION = '^2.1.9';
579
- const I18NEXT_VERSION = '26.2.0';
580
- const REACT_VERSION = '^19.2.6';
581
- const REACT_DOM_VERSION = '^19.2.6';
582
- const REACT_ROUTER_DOM_VERSION = '7.16.0';
638
+ const I18NEXT_VERSION = '26.3.1';
639
+ const REACT_VERSION = '^19.2.7';
640
+ const REACT_DOM_VERSION = '^19.2.7';
641
+ const REACT_ROUTER_DOM_VERSION = '7.17.0';
583
642
  const PNPM_VERSION = '11.5.0';
584
- const WORKSPACE_PACKAGE_VERSION = 'workspace:*';
585
643
  const GENERATED_CONTRACT_PATH = '.modernjs/ultramodern-generated-contract.json';
586
644
  const RSTACK_AGENT_SKILLS_COMMIT = '61c948b42512e223bad44b83af4080eba48b2677';
587
645
  const MODULE_FEDERATION_AGENT_SKILLS_COMMIT = '07bb5b6c43ad457609e00c081b72d4c42508ec76';
@@ -605,13 +663,6 @@ const privateAgentSkills = [
605
663
  'debugger-mode'
606
664
  ];
607
665
  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);\"";
608
- const modernPackageNames = [
609
- '@modern-js/app-tools',
610
- '@modern-js/plugin-bff',
611
- '@modern-js/plugin-i18n',
612
- '@modern-js/plugin-tanstack',
613
- '@modern-js/runtime'
614
- ];
615
666
  function sortJsonValue(value) {
616
667
  if (Array.isArray(value)) return value.map(sortJsonValue);
617
668
  if (null !== value && 'object' == typeof value) return Object.fromEntries(Object.entries(value).sort(([left], [right])=>left.localeCompare(right)).map(([key, entry])=>[
@@ -620,6 +671,10 @@ function sortJsonValue(value) {
620
671
  ]));
621
672
  return value;
622
673
  }
674
+ const supportedWorkspaceLanguages = [
675
+ 'en',
676
+ 'cs'
677
+ ];
623
678
  const ULTRAMODERN_WORKSPACE_FLAG = '--ultramodern-workspace';
624
679
  const FIRST_VERTICAL_PORT = 4101;
625
680
  const TAILWIND_PREFIX_DIGIT_WORDS = [
@@ -914,28 +969,23 @@ function relativeRootFor(packageDir) {
914
969
  return normalizePath(node_path.relative(packageDir, '.') || '.');
915
970
  }
916
971
  function resolvePackageSource(options) {
917
- const strategy = options.packageSource?.strategy ?? 'workspace';
918
- return {
972
+ const strategy = options.packageSource?.strategy ?? 'install';
973
+ if ('workspace' === strategy) return {
919
974
  strategy,
920
- modernPackageVersion: 'install' === strategy ? options.packageSource?.modernPackageVersion ?? options.modernVersion : WORKSPACE_PACKAGE_VERSION,
975
+ modernPackageVersion: WORKSPACE_PACKAGE_VERSION,
921
976
  registry: options.packageSource?.registry,
922
977
  aliasScope: options.packageSource?.aliasScope,
923
978
  aliasPackageNamePrefix: options.packageSource?.aliasPackageNamePrefix
924
979
  };
925
- }
926
- function modernPackageVersion(packageSource) {
927
- return 'install' === packageSource.strategy ? packageSource.modernPackageVersion : WORKSPACE_PACKAGE_VERSION;
928
- }
929
- function modernAliasPackageName(packageName, packageSource) {
930
- if (!packageSource.aliasScope) return packageName;
931
- const scope = packageSource.aliasScope.replace(/^@/, '');
932
- const unscopedName = packageName.split('/').at(-1);
933
- return `@${scope}/${packageSource.aliasPackageNamePrefix ?? ''}${unscopedName}`;
934
- }
935
- function modernPackageSpecifier(packageName, packageSource) {
936
- if ('install' !== packageSource.strategy) return WORKSPACE_PACKAGE_VERSION;
937
- if (!packageSource.aliasScope) return packageSource.modernPackageVersion;
938
- return `npm:${modernAliasPackageName(packageName, packageSource)}@${packageSource.modernPackageVersion}`;
980
+ const registry = options.packageSource?.registry;
981
+ const aliasScope = options.packageSource?.aliasScope ?? (registry ? void 0 : BLEEDINGDEV_PACKAGE_SCOPE);
982
+ return {
983
+ strategy,
984
+ modernPackageVersion: options.packageSource?.modernPackageVersion ?? options.modernVersion,
985
+ registry,
986
+ aliasScope,
987
+ aliasPackageNamePrefix: options.packageSource?.aliasPackageNamePrefix ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
988
+ };
939
989
  }
940
990
  function appDependencies(scope, packageSource, app, remotes = []) {
941
991
  const dependencies = {
@@ -968,13 +1018,13 @@ function appDevDependencies(packageSource, enableTailwind) {
968
1018
  '@effect/tsgo': EFFECT_TSGO_VERSION,
969
1019
  ...enableTailwind ? {
970
1020
  '@tailwindcss/postcss': `^${TAILWIND_POSTCSS_VERSION}`,
971
- postcss: '^8.5.6',
1021
+ postcss: `^${POSTCSS_VERSION}`,
972
1022
  tailwindcss: `^${TAILWIND_VERSION}`
973
1023
  } : {},
974
1024
  "@typescript/native-preview": TYPESCRIPT_NATIVE_PREVIEW_VERSION,
975
1025
  '@types/node': '^20',
976
- '@types/react': '^19.1.8',
977
- '@types/react-dom': '^19.1.6',
1026
+ '@types/react': '^19.2.17',
1027
+ '@types/react-dom': '^19.2.3',
978
1028
  typescript: TYPESCRIPT_VERSION,
979
1029
  'zephyr-rspack-plugin': ZEPHYR_RSPACK_PLUGIN_VERSION,
980
1030
  wrangler: WRANGLER_VERSION
@@ -1420,7 +1470,19 @@ if (
1420
1470
  export default defineConfig(
1421
1471
  presetUltramodern(
1422
1472
  {
1423
- ${bffConfig} html: {
1473
+ ${bffConfig} ...(cloudflareDeployEnabled
1474
+ ? {
1475
+ deploy: {
1476
+ worker: {
1477
+ compatibilityDate: '${CLOUDFLARE_COMPATIBILITY_DATE}',
1478
+ name: cloudflareWorkerName,
1479
+ security: ${formatTsJsonValue(sortJsonValue(createCloudflareSecurityContract()), 16)},
1480
+ ssr: true,
1481
+ },
1482
+ },
1483
+ }
1484
+ : {}),
1485
+ html: {
1424
1486
  outputStructure: 'flat',
1425
1487
  },
1426
1488
  output: {
@@ -1457,6 +1519,9 @@ ${bffConfig} html: {
1457
1519
  '/mf-manifest.json',
1458
1520
  '/mf-stats.json',
1459
1521
  '/remoteEntry.js',
1522
+ '/robots.txt',
1523
+ '/site.webmanifest',
1524
+ '/sitemap.xml',
1460
1525
  '/static',
1461
1526
  '/zephyr-manifest.json',
1462
1527
  ],
@@ -1469,6 +1534,20 @@ ${bffConfig} html: {
1469
1534
  ${bffPluginEntry} moduleFederationPlugin(),
1470
1535
  zephyrRspackPlugin(),
1471
1536
  ],
1537
+ server: {
1538
+ port,
1539
+ publicDir: ['./locales', './assets'],
1540
+ ssr: {
1541
+ mode: 'string',
1542
+ moduleFederationAppSSR: true,
1543
+ },
1544
+ },
1545
+ source: {
1546
+ globalVars: {
1547
+ ULTRAMODERN_SITE_URL: siteUrl,
1548
+ },
1549
+ mainEntryName: 'index',
1550
+ },
1472
1551
  tools: {
1473
1552
  autoprefixer: {
1474
1553
  overrideBrowserslist: ['defaults'],
@@ -1485,31 +1564,6 @@ ${bffPluginEntry} moduleFederationPlugin(),
1485
1564
  ]);
1486
1565
  },
1487
1566
  },
1488
- ...(cloudflareDeployEnabled
1489
- ? {
1490
- deploy: {
1491
- worker: {
1492
- compatibilityDate: '${CLOUDFLARE_COMPATIBILITY_DATE}',
1493
- security: ${formatTsJsonValue(createCloudflareSecurityContract(), 16)},
1494
- ssr: true,
1495
- },
1496
- },
1497
- }
1498
- : {}),
1499
- server: {
1500
- port,
1501
- publicDir: ['./locales', './assets'],
1502
- ssr: {
1503
- mode: 'string',
1504
- moduleFederationAppSSR: true,
1505
- },
1506
- },
1507
- source: {
1508
- globalVars: {
1509
- ULTRAMODERN_SITE_URL: siteUrl,
1510
- },
1511
- mainEntryName: 'index',
1512
- },
1513
1567
  },
1514
1568
  {
1515
1569
  appId,
@@ -2128,15 +2182,125 @@ function createPostcssConfig() {
2128
2182
  function createTailwindConfig() {
2129
2183
  return `import type { Config } from 'tailwindcss';
2130
2184
 
2131
- export default {
2132
- } satisfies Config;
2185
+ export default {} satisfies Config;
2133
2186
  `;
2134
2187
  }
2135
2188
  function createTw(prefix) {
2136
2189
  return (classList)=>classList.split(/\s+/u).filter(Boolean).map((candidate)=>`${prefix}:${candidate.replace(/\[&&\]:/gu, '')}`).join(' ');
2137
2190
  }
2138
- function workspaceAssetsForApp(_app) {
2139
- return {};
2191
+ const publicSurfaceRequiredAssetPaths = [
2192
+ 'config/public/robots.txt'
2193
+ ];
2194
+ const publicSurfaceOptionalAssetPaths = [
2195
+ 'config/public/sitemap.xml',
2196
+ 'config/public/site.webmanifest'
2197
+ ];
2198
+ function normalisePublicPath(pathname) {
2199
+ const normalised = pathname.trim().replaceAll(/\/+/gu, '/').replace(/\/+$/u, '');
2200
+ return normalised.length > 0 && normalised.startsWith('/') ? normalised : `/${normalised}`;
2201
+ }
2202
+ function createLocalisedPublicPath(pathname, language) {
2203
+ const publicPath = normalisePublicPath(pathname);
2204
+ return '/' === publicPath ? `/${language}` : `/${language}${publicPath}`;
2205
+ }
2206
+ function isConcretePublicPath(pathname) {
2207
+ return !normalisePublicPath(pathname).split('/').some((segment)=>segment.startsWith(':') || segment.includes('*') || segment.startsWith('['));
2208
+ }
2209
+ function uniqueSorted(values) {
2210
+ return Array.from(new Set(values)).sort((left, right)=>left.localeCompare(right));
2211
+ }
2212
+ function createPublicSurfaceRouteEntries(app) {
2213
+ return createPublicRouteMetadata(app).map((route)=>{
2214
+ const localeUrlPaths = Object.fromEntries(supportedWorkspaceLanguages.map((language)=>[
2215
+ language,
2216
+ createLocalisedPublicPath(route.localisedPaths[language], language)
2217
+ ]));
2218
+ if (!Object.values(localeUrlPaths).every(isConcretePublicPath)) return;
2219
+ return {
2220
+ ...route,
2221
+ canonicalUrlPath: localeUrlPaths.en,
2222
+ localeUrlPaths
2223
+ };
2224
+ }).filter((route)=>void 0 !== route).sort((left, right)=>left.canonicalUrlPath.localeCompare(right.canonicalUrlPath) || left.id.localeCompare(right.id));
2225
+ }
2226
+ function createPublicSurfaceUrlPaths(app) {
2227
+ return uniqueSorted(createPublicSurfaceRouteEntries(app).flatMap((route)=>supportedWorkspaceLanguages.map((language)=>route.localeUrlPaths[language])));
2228
+ }
2229
+ function createPublicSurfaceOrigin(app) {
2230
+ return `http://localhost:${app.port}`;
2231
+ }
2232
+ function escapeXmlText(value) {
2233
+ return value.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;');
2234
+ }
2235
+ function escapeXmlAttribute(value) {
2236
+ return escapeXmlText(value).replaceAll('"', '&quot;');
2237
+ }
2238
+ function renderRobotsTxt(app) {
2239
+ const urlPaths = createPublicSurfaceUrlPaths(app);
2240
+ const lines = [
2241
+ 'User-agent: *'
2242
+ ];
2243
+ if (0 === urlPaths.length) lines.push('Disallow: /');
2244
+ else {
2245
+ for (const urlPath of urlPaths)lines.push(`Allow: ${urlPath}$`);
2246
+ lines.push('Disallow: /');
2247
+ lines.push(`Sitemap: ${createPublicSurfaceOrigin(app)}/sitemap.xml`);
2248
+ }
2249
+ return `${lines.join('\n')}\n`;
2250
+ }
2251
+ function renderSitemapXml(app) {
2252
+ const origin = createPublicSurfaceOrigin(app);
2253
+ const routes = createPublicSurfaceRouteEntries(app);
2254
+ const lines = [
2255
+ '<?xml version="1.0" encoding="UTF-8"?>',
2256
+ '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">'
2257
+ ];
2258
+ for (const route of routes)for (const language of supportedWorkspaceLanguages){
2259
+ lines.push(' <url>');
2260
+ lines.push(` <loc>${escapeXmlText(`${origin}${route.localeUrlPaths[language]}`)}</loc>`);
2261
+ for (const alternateLanguage of supportedWorkspaceLanguages)lines.push(` <xhtml:link rel="alternate" hreflang="${alternateLanguage}" href="${escapeXmlAttribute(`${origin}${route.localeUrlPaths[alternateLanguage]}`)}" />`);
2262
+ lines.push(` <xhtml:link rel="alternate" hreflang="x-default" href="${escapeXmlAttribute(`${origin}${route.localeUrlPaths.en}`)}" />`);
2263
+ lines.push(' </url>');
2264
+ }
2265
+ lines.push('</urlset>');
2266
+ return `${lines.join('\n')}\n`;
2267
+ }
2268
+ function renderWebManifest(app) {
2269
+ const startUrl = createPublicSurfaceUrlPaths(app)[0];
2270
+ const manifest = {
2271
+ name: app.displayName,
2272
+ short_name: app.displayName,
2273
+ display: 'standalone',
2274
+ background_color: '#ffffff',
2275
+ theme_color: '#133225',
2276
+ lang: 'en',
2277
+ categories: [
2278
+ 'business',
2279
+ 'productivity'
2280
+ ],
2281
+ icons: [],
2282
+ ...startUrl ? {
2283
+ scope: '/',
2284
+ start_url: startUrl
2285
+ } : {}
2286
+ };
2287
+ return `${JSON.stringify(sortJsonValue(manifest), null, 2)}\n`;
2288
+ }
2289
+ function createPublicSurfaceAssets(app) {
2290
+ const assets = {
2291
+ 'config/public/robots.txt': renderRobotsTxt(app)
2292
+ };
2293
+ if (createPublicSurfaceRouteEntries(app).length > 0) {
2294
+ assets['config/public/sitemap.xml'] = renderSitemapXml(app);
2295
+ assets['config/public/site.webmanifest'] = renderWebManifest(app);
2296
+ }
2297
+ return assets;
2298
+ }
2299
+ function workspaceAssetsForApp(app) {
2300
+ return createPublicSurfaceAssets(app);
2301
+ }
2302
+ function rewriteWorkspaceAssetsForApp(workspaceRoot, app) {
2303
+ for (const [relativePath, content] of Object.entries(workspaceAssetsForApp(app)))writeFileReplacing(workspaceRoot, `${app.directory}/${relativePath}`, content);
2140
2304
  }
2141
2305
  function createLocalizedHeadComponent() {
2142
2306
  return `const fallbackLanguage = 'en';
@@ -3534,7 +3698,7 @@ export const ${apiExport} = HttpApi.make('${apiName}').add(
3534
3698
  .add(
3535
3699
  HttpApiEndpoint.get('list', '/effect/${stem}', {
3536
3700
  query: {
3537
- limit: Schema.optional(Schema.NumberFromString),
3701
+ limit: Schema.optional(Schema.FiniteFromString),
3538
3702
  },
3539
3703
  success: Schema.Struct({
3540
3704
  items: Schema.Array(${schemaExport}),
@@ -4086,19 +4250,10 @@ function createDevelopmentOverlay(remotes = []) {
4086
4250
  };
4087
4251
  }
4088
4252
  function createPackageSourceMetadata(scope, packageSource) {
4089
- const modernPackages = {
4090
- packages: modernPackageNames,
4091
- specifier: modernPackageVersion(packageSource)
4092
- };
4093
- if (packageSource.registry) modernPackages.registry = packageSource.registry;
4094
- if (packageSource.aliasScope) modernPackages.aliases = Object.fromEntries(modernPackageNames.map((packageName)=>[
4095
- packageName,
4096
- modernAliasPackageName(packageName, packageSource)
4097
- ]));
4098
4253
  return {
4099
4254
  schemaVersion: 1,
4100
4255
  strategy: packageSource.strategy,
4101
- modernPackages,
4256
+ modernPackages: createModernPackagesMetadata(ULTRAMODERN_WORKSPACE_MODERN_PACKAGES, packageSource),
4102
4257
  generatedWorkspacePackages: {
4103
4258
  packages: sharedPackages.map((sharedPackage)=>ultramodern_workspace_packageName(scope, sharedPackage.id)),
4104
4259
  specifier: WORKSPACE_PACKAGE_VERSION
@@ -4348,6 +4503,23 @@ function createStylingContract(scope, app, enableTailwind) {
4348
4503
  federation: createAppCssFederationContract(scope, app)
4349
4504
  };
4350
4505
  }
4506
+ function createPublicSurfaceContract(app) {
4507
+ const files = Object.keys(createPublicSurfaceAssets(app)).sort().map((relativePath)=>relativePath.replace(/^config\/public\//u, ''));
4508
+ return {
4509
+ source: 'route-owned-public-routes',
4510
+ metadataExport: './src/routes/ultramodern-route-metadata',
4511
+ staticRoot: 'config/public',
4512
+ privateRoutePolicy: 'omit-from-generated-public-surface',
4513
+ files,
4514
+ omittedByDefault: [
4515
+ 'api-catalog.json',
4516
+ 'llms.txt',
4517
+ 'security.txt'
4518
+ ],
4519
+ publicRoutes: createPublicRouteMetadata(app),
4520
+ concreteUrlPaths: createPublicSurfaceUrlPaths(app)
4521
+ };
4522
+ }
4351
4523
  function createAppGeneratedContract(scope, app, apps, enableTailwind) {
4352
4524
  const appWithResolvedRefs = 'shell' === app.kind ? {
4353
4525
  ...app,
@@ -4416,7 +4588,8 @@ function createAppGeneratedContract(scope, app, apps, enableTailwind) {
4416
4588
  privateByDefault: true,
4417
4589
  publicnessDefault: 'private-app-screen',
4418
4590
  generatedRouteMap: true,
4419
- manualOverrides: []
4591
+ manualOverrides: [],
4592
+ publicSurface: createPublicSurfaceContract(app)
4420
4593
  },
4421
4594
  moduleFederation: {
4422
4595
  name: app.mfName,
@@ -4908,6 +5081,21 @@ const expectedBuildScript = ${JSON.stringify(expectedBuildScript)};
4908
5081
  const expectedCloudflareBuildScript = ${JSON.stringify(expectedCloudflareBuildScript)};
4909
5082
  const expectedCloudflareDeployScript = ${JSON.stringify(expectedCloudflareDeployScript)};
4910
5083
  const expectedCloudflareSecurity = ${JSON.stringify(expectedCloudflareSecurity, null, 2)};
5084
+ const publicSurfaceRequiredAssetPaths = ${JSON.stringify([
5085
+ ...publicSurfaceRequiredAssetPaths
5086
+ ], null, 2)};
5087
+ const publicSurfaceOptionalAssetPaths = ${JSON.stringify([
5088
+ ...publicSurfaceOptionalAssetPaths
5089
+ ], null, 2)};
5090
+ const expectedModernPackageSpecifier = packageName => {
5091
+ if (packageSource.strategy === 'workspace') {
5092
+ return 'workspace:*';
5093
+ }
5094
+ const aliases = packageSource.modernPackages?.aliases ?? {};
5095
+ const alias = aliases[packageName];
5096
+ const specifier = packageSource.modernPackages?.specifier;
5097
+ return typeof alias === 'string' ? \`npm:\${alias}@\${specifier}\` : specifier;
5098
+ };
4911
5099
 
4912
5100
  const readText = relativePath => fs.readFileSync(path.join(root, relativePath), 'utf-8');
4913
5101
  const readJson = relativePath => JSON.parse(readText(relativePath));
@@ -4922,6 +5110,21 @@ const assertExists = relativePath => {
4922
5110
  const assertNotExists = relativePath => {
4923
5111
  assert(!fs.existsSync(path.join(root, relativePath)), \`Unexpected \${relativePath}\`);
4924
5112
  };
5113
+ const assertPublicSurfaceAssets = (appPath, publicRoutes) => {
5114
+ const robots = readText(\`\${appPath}/config/public/robots.txt\`);
5115
+ if ((publicRoutes ?? []).length === 0) {
5116
+ assert(robots.includes('Disallow: /'), \`\${appPath} robots.txt must disallow crawling when no public routes exist\`);
5117
+ for (const relativePath of publicSurfaceOptionalAssetPaths) {
5118
+ assertNotExists(\`\${appPath}/\${relativePath}\`);
5119
+ }
5120
+ return;
5121
+ }
5122
+ const sitemap = readText(\`\${appPath}/config/public/sitemap.xml\`);
5123
+ const manifest = readJson(\`\${appPath}/config/public/site.webmanifest\`);
5124
+ assert(!sitemap.includes('<lastmod>'), \`\${appPath} sitemap must omit build-time lastmod values\`);
5125
+ assert(typeof manifest.name === 'string' && manifest.name.length > 0, \`\${appPath} web manifest must include a safe app name\`);
5126
+ assert(typeof manifest.start_url === 'string' && manifest.start_url.startsWith('/'), \`\${appPath} web manifest start_url must be a public route path\`);
5127
+ };
4925
5128
  const expectedWorkerName = packageSuffix => \`\${packageScope}-\${packageSuffix}\`.slice(0, 63);
4926
5129
  const expectedChunkLoadingGlobal = mfName =>
4927
5130
  \`__ULTRAMODERN_\${mfName
@@ -4998,6 +5201,9 @@ const requiredPaths = [
4998
5201
  'apps/shell-super-app/src/routes/layout.tsx',
4999
5202
  'apps/shell-super-app/src/routes/ultramodern-route-metadata.ts',
5000
5203
  'apps/shell-super-app/src/routes/[lang]/page.tsx',
5204
+ ...publicSurfaceRequiredAssetPaths.map(
5205
+ relativePath => \`apps/shell-super-app/\${relativePath}\`,
5206
+ ),
5001
5207
  'packages/shared-contracts/src/index.ts',
5002
5208
  'packages/shared-design-tokens/src/index.ts',
5003
5209
  'packages/shared-design-tokens/src/tokens.css',
@@ -5024,6 +5230,9 @@ for (const vertical of fullStackVerticals) {
5024
5230
  \`\${vertical.path}/src/routes/layout.tsx\`,
5025
5231
  \`\${vertical.path}/src/routes/ultramodern-route-metadata.ts\`,
5026
5232
  \`\${vertical.path}/src/routes/[lang]/page.tsx\`,
5233
+ ...publicSurfaceRequiredAssetPaths.map(
5234
+ relativePath => \`\${vertical.path}/\${relativePath}\`,
5235
+ ),
5027
5236
  ...vertical.routePagePaths,
5028
5237
  );
5029
5238
  }
@@ -5058,6 +5267,31 @@ assert(rootPackage.modernjs?.preset === 'presetUltramodern', 'Root must declare
5058
5267
  assert(rootPackage.modernjs?.packageSource?.config === './.modernjs/ultramodern-package-source.json', 'Root must point at package source metadata');
5059
5268
  assert(rootPackage.modernjs?.packageSource?.strategy === packageSource.strategy, 'Root package source strategy must match metadata');
5060
5269
  assert(packageSource.strategy === 'workspace' || packageSource.strategy === 'install', 'Package source strategy must be workspace or install');
5270
+ assert(packageSource.strategy === 'install' || packageSource.modernPackages?.specifier === 'workspace:*', 'Workspace package source must be explicitly backed by workspace:*');
5271
+ if (packageSource.strategy === 'install') {
5272
+ const installSpecifier = packageSource.modernPackages?.specifier;
5273
+ assert(
5274
+ typeof installSpecifier === 'string' &&
5275
+ /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/.test(installSpecifier) &&
5276
+ installSpecifier.includes('ultramodern'),
5277
+ 'Install package source must use a semver UltraModern published cohort',
5278
+ );
5279
+ const modernAliases = packageSource.modernPackages?.aliases ?? {};
5280
+ if (Object.keys(modernAliases).length > 0) {
5281
+ for (const modernPackageName of [
5282
+ '@modern-js/app-tools',
5283
+ '@modern-js/plugin-bff',
5284
+ '@modern-js/plugin-i18n',
5285
+ '@modern-js/plugin-tanstack',
5286
+ '@modern-js/runtime',
5287
+ ]) {
5288
+ assert(
5289
+ /^@[^/]+\\/.+/.test(modernAliases[modernPackageName] ?? ''),
5290
+ \`Install package source alias for \${modernPackageName} must be a scoped npm package\`,
5291
+ );
5292
+ }
5293
+ }
5294
+ }
5061
5295
  assert(packageSource.generatedWorkspacePackages?.specifier === 'workspace:*', 'Generated workspace packages must keep workspace:* links');
5062
5296
  assert(
5063
5297
  rootPackage.scripts?.build === expectedBuildScript,
@@ -5072,6 +5306,10 @@ assert(rootPackage.scripts?.['cloudflare:proof'] === 'node ./scripts/proof-cloud
5072
5306
  assert(rootPackage.scripts?.['skills:install'] === 'node ./scripts/bootstrap-agent-skills.mjs', 'Root must expose skills:install');
5073
5307
  assert(rootPackage.scripts?.['skills:check'] === 'node ./scripts/bootstrap-agent-skills.mjs --check', 'Root must expose skills:check');
5074
5308
  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');
5309
+ const agentReferenceRepoSetup = readText('scripts/setup-agent-reference-repos.mjs');
5310
+ assert(agentReferenceRepoSetup.includes("['commit', '--no-verify', '-m', message]"), 'Agent reference repo installer commits must skip hooks during postinstall');
5311
+ assert(agentReferenceRepoSetup.includes("commitInstallerChanges('Initialize UltraModern workspace')"), 'Initial agent reference repo commit must use the installer commit helper');
5312
+ assert(agentReferenceRepoSetup.includes("commitInstallerChanges('Record agent reference repo manifest')"), 'Agent reference repo manifest commit must use the installer commit helper');
5075
5313
 
5076
5314
  const expectedAppIds = ['shell-super-app', ...fullStackVerticals.map(vertical => vertical.id)];
5077
5315
  const expectedCloudflareCompatibilityDate = '${CLOUDFLARE_COMPATIBILITY_DATE}';
@@ -5091,6 +5329,7 @@ assert(generatedContract.cssFederation?.sharedDesignTokens?.dedupe?.duplicateBas
5091
5329
  assert(generatedContract.cssFederation?.sharedDesignTokens?.ssr?.firstPaintRequired === true, 'Shared design token CSS must be required for SSR first paint');
5092
5330
 
5093
5331
  const shellPackage = readJson('apps/shell-super-app/package.json');
5332
+ const shellModernConfig = readText('apps/shell-super-app/modern.config.ts');
5094
5333
  const expectedZephyrDependencies = Object.fromEntries(
5095
5334
  fullStackVerticals.map(vertical => [
5096
5335
  vertical.zephyrAlias,
@@ -5102,6 +5341,11 @@ assert(
5102
5341
  JSON.stringify(expectedZephyrDependencies),
5103
5342
  'Shell Zephyr dependencies must reference every vertical package',
5104
5343
  );
5344
+ assert(shellPackage.devDependencies?.['@modern-js/app-tools'] === expectedModernPackageSpecifier('@modern-js/app-tools'), 'Shell app-tools dependency must match package source metadata');
5345
+ assert(shellPackage.dependencies?.['@modern-js/plugin-bff'] === expectedModernPackageSpecifier('@modern-js/plugin-bff'), 'Shell plugin-bff dependency must match package source metadata');
5346
+ assert(shellPackage.dependencies?.['@modern-js/plugin-i18n'] === expectedModernPackageSpecifier('@modern-js/plugin-i18n'), 'Shell plugin-i18n dependency must match package source metadata');
5347
+ assert(shellPackage.dependencies?.['@modern-js/plugin-tanstack'] === expectedModernPackageSpecifier('@modern-js/plugin-tanstack'), 'Shell plugin-tanstack dependency must match package source metadata');
5348
+ assert(shellPackage.dependencies?.['@modern-js/runtime'] === expectedModernPackageSpecifier('@modern-js/runtime'), 'Shell runtime dependency must match package source metadata');
5105
5349
  const shellContract = generatedContract.apps?.find(app => app.id === 'shell-super-app');
5106
5350
  assert(shellContract?.deploy?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell Cloudflare workerName is incorrect');
5107
5351
  assert(shellContract?.deploy?.cloudflare?.publicUrlEnv === 'ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP', 'Shell Cloudflare public URL env is incorrect');
@@ -5109,6 +5353,9 @@ assert(shellContract?.deploy?.cloudflare?.compatibilityDate === expectedCloudfla
5109
5353
  assert(JSON.stringify(shellContract?.deploy?.cloudflare?.compatibilityFlags) === JSON.stringify(expectedCloudflareCompatibilityFlags), 'Shell Cloudflare compatibility flags are incorrect');
5110
5354
  assert(JSON.stringify(shellContract?.deploy?.cloudflare?.security) === JSON.stringify(expectedCloudflareSecurity), 'Shell Cloudflare security contract is incorrect');
5111
5355
  assert(shellContract?.deploy?.worker?.compatibilityDate === expectedCloudflareCompatibilityDate, 'Shell worker compatibilityDate is incorrect');
5356
+ assert(shellContract?.deploy?.worker?.name === expectedWorkerName('shell-super-app'), 'Shell worker name is incorrect');
5357
+ assert(shellModernConfig.includes("const cloudflareWorkerName = '" + expectedWorkerName('shell-super-app') + "'"), 'Shell modern.config.ts must define the Cloudflare worker name');
5358
+ assert(shellModernConfig.includes('name: cloudflareWorkerName'), 'Shell modern.config.ts must wire deploy.worker.name');
5112
5359
  assert(shellContract?.config?.rspack?.output?.uniqueName === 'shellSuperApp', 'Shell Rspack uniqueName is incorrect');
5113
5360
  assert(shellContract?.config?.rspack?.output?.chunkLoadingGlobal === expectedChunkLoadingGlobal('shellSuperApp'), 'Shell Rspack chunkLoadingGlobal is incorrect');
5114
5361
  assert(topology.shell?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell topology Cloudflare workerName is incorrect');
@@ -5129,6 +5376,7 @@ assert(
5129
5376
  (shellContract?.routes?.owned ?? []).every(route => route.public === false && route.indexable === false && route.publicSurface === 'private-app-screen'),
5130
5377
  'Shell owned routes must be non-indexable private app screens by default',
5131
5378
  );
5379
+ assertPublicSurfaceAssets('apps/shell-super-app', shellContract?.routes?.publicRoutes ?? []);
5132
5380
  assert(
5133
5381
  topology.shell?.verticalRefs?.join(',') === fullStackVerticals.map(vertical => vertical.id).join(','),
5134
5382
  'Topology shell verticalRefs must match generated verticals',
@@ -5139,10 +5387,15 @@ assert(!('effectServices' in topology), 'Default APIs must be vertical-owned, no
5139
5387
 
5140
5388
  for (const vertical of fullStackVerticals) {
5141
5389
  const packageJson = readJson(\`\${vertical.path}/package.json\`);
5390
+ const modernConfig = readText(\`\${vertical.path}/modern.config.ts\`);
5142
5391
  assert(packageJson.name === vertical.packageName, \`\${vertical.id} package name is incorrect\`);
5143
5392
  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\`);
5144
5393
  assert(packageJson.scripts?.['cloudflare:proof']?.includes(\`--app \${vertical.id}\`), \`\${vertical.id} must expose cloudflare:proof\`);
5145
- assert(packageJson.dependencies?.['@modern-js/plugin-bff'], \`\${vertical.id} must depend on plugin-bff\`);
5394
+ assert(packageJson.devDependencies?.['@modern-js/app-tools'] === expectedModernPackageSpecifier('@modern-js/app-tools'), \`\${vertical.id} app-tools dependency must match package source metadata\`);
5395
+ assert(packageJson.dependencies?.['@modern-js/plugin-bff'] === expectedModernPackageSpecifier('@modern-js/plugin-bff'), \`\${vertical.id} plugin-bff dependency must match package source metadata\`);
5396
+ assert(packageJson.dependencies?.['@modern-js/plugin-i18n'] === expectedModernPackageSpecifier('@modern-js/plugin-i18n'), \`\${vertical.id} plugin-i18n dependency must match package source metadata\`);
5397
+ assert(packageJson.dependencies?.['@modern-js/plugin-tanstack'] === expectedModernPackageSpecifier('@modern-js/plugin-tanstack'), \`\${vertical.id} plugin-tanstack dependency must match package source metadata\`);
5398
+ assert(packageJson.dependencies?.['@modern-js/runtime'] === expectedModernPackageSpecifier('@modern-js/runtime'), \`\${vertical.id} runtime dependency must match package source metadata\`);
5146
5399
  assert(packageJson.exports?.['./effect/client'] === \`./src/effect/\${vertical.stem}-client.ts\`, \`\${vertical.id} must export its Effect client\`);
5147
5400
  assert(packageJson.exports?.['./shared/effect/api'] === './shared/effect/api.ts', \`\${vertical.id} must export its Effect API contract\`);
5148
5401
  const expectedVerticalZephyrDependencies = Object.fromEntries(
@@ -5168,6 +5421,9 @@ for (const vertical of fullStackVerticals) {
5168
5421
  assert(JSON.stringify(contractEntry?.deploy?.cloudflare?.compatibilityFlags) === JSON.stringify(expectedCloudflareCompatibilityFlags), \`\${vertical.id} Cloudflare compatibility flags are incorrect\`);
5169
5422
  assert(JSON.stringify(contractEntry?.deploy?.cloudflare?.security) === JSON.stringify(expectedCloudflareSecurity), \`\${vertical.id} Cloudflare security contract is incorrect\`);
5170
5423
  assert(contractEntry?.deploy?.worker?.compatibilityDate === expectedCloudflareCompatibilityDate, \`\${vertical.id} worker compatibilityDate is incorrect\`);
5424
+ assert(contractEntry?.deploy?.worker?.name === expectedWorkerName(vertical.id), \`\${vertical.id} worker name is incorrect\`);
5425
+ assert(modernConfig.includes("const cloudflareWorkerName = '" + expectedWorkerName(vertical.id) + "'"), \`\${vertical.id} modern.config.ts must define the Cloudflare worker name\`);
5426
+ assert(modernConfig.includes('name: cloudflareWorkerName'), \`\${vertical.id} modern.config.ts must wire deploy.worker.name\`);
5171
5427
  assert(contractEntry?.deploy?.cloudflare?.routes?.effectReadiness === \`\${vertical.apiPrefix}/effect/\${vertical.stem}/readiness\`, \`\${vertical.id} Cloudflare proof readiness route is incorrect\`);
5172
5428
  assert(contractEntry?.config?.rspack?.output?.uniqueName === vertical.mfName, \`\${vertical.id} Rspack uniqueName is incorrect\`);
5173
5429
  assert(contractEntry?.config?.rspack?.output?.chunkLoadingGlobal === expectedChunkLoadingGlobal(vertical.mfName), \`\${vertical.id} Rspack chunkLoadingGlobal is incorrect\`);
@@ -5201,6 +5457,7 @@ for (const vertical of fullStackVerticals) {
5201
5457
  (contractEntry?.routes?.owned ?? []).every(route => route.public === false && route.indexable === false && route.publicSurface === 'private-app-screen'),
5202
5458
  \`\${vertical.id} owned routes must be non-indexable private app screens by default\`,
5203
5459
  );
5460
+ assertPublicSurfaceAssets(vertical.path, contractEntry?.routes?.publicRoutes ?? []);
5204
5461
  assert(contractEntry?.styling?.federation?.owner?.id === vertical.id, \`\${vertical.id} CSS federation owner is missing\`);
5205
5462
  assert(contractEntry?.styling?.federation?.role === 'vertical-css', \`\${vertical.id} must own only vertical CSS\`);
5206
5463
  assert(contractEntry?.styling?.federation?.rootSelector === \`[data-app-id="\${vertical.id}"]\`, \`\${vertical.id} CSS root selector is incorrect\`);
@@ -5859,6 +6116,7 @@ function rewriteShellAppFiles(workspaceRoot, scope, packageSource, enableTailwin
5859
6116
  writeJsonFile(node_path.join(workspaceRoot, `${shellApp.directory}/package.json`), createAppPackage(scope, shellHost, packageSource, enableTailwind, remotes));
5860
6117
  writeFileReplacing(workspaceRoot, `${shellApp.directory}/src/modern-app-env.d.ts`, createAppEnvDts(shellHost, remotes));
5861
6118
  writeFileReplacing(workspaceRoot, `${shellApp.directory}/src/routes/ultramodern-route-metadata.ts`, createRouteMetadataModule(shellHost));
6119
+ rewriteWorkspaceAssetsForApp(workspaceRoot, shellHost);
5862
6120
  writeFileReplacing(workspaceRoot, `${shellApp.directory}/src/modern.runtime.ts`, createAppRuntimeConfig(shellHost, scope, remotes));
5863
6121
  writeJsonFile(node_path.join(workspaceRoot, `${shellApp.directory}/locales/en/translation.json`), createAppPublicLocaleMessages(shellHost, 'en', remotes));
5864
6122
  writeJsonFile(node_path.join(workspaceRoot, `${shellApp.directory}/locales/en/${appI18nNamespace(shellHost)}.json`), createAppPublicLocaleMessages(shellHost, 'en', remotes));
@@ -6066,10 +6324,24 @@ const sha1Pattern = /^[0-9a-f]{40}$/;
6066
6324
  const sha256Pattern = /^[0-9a-f]{64}$/;
6067
6325
  const templateIdPattern = /^[a-z0-9][a-z0-9._-]*$/;
6068
6326
  const packageNamePattern = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/;
6069
- const src_TANSTACK_ROUTER_VERSION = '1.170.11';
6327
+ const src_TANSTACK_ROUTER_VERSION = '1.170.15';
6070
6328
  const src_TAILWIND_VERSION = '4.3.0';
6071
6329
  const src_TAILWIND_POSTCSS_VERSION = '4.3.0';
6072
6330
  const src_PNPM_VERSION = '11.5.0';
6331
+ const src_I18NEXT_VERSION = '26.3.1';
6332
+ const src_REACT_VERSION = '^19.2.7';
6333
+ const src_REACT_DOM_VERSION = '^19.2.7';
6334
+ const REACT_I18NEXT_VERSION = '17.0.8';
6335
+ const src_EFFECT_TSGO_VERSION = '0.14.0';
6336
+ const src_TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260606.1';
6337
+ const HAPPY_DOM_VERSION = '^20.10.1';
6338
+ const RSTEST_CORE_VERSION = '0.10.3';
6339
+ const src_OXFMT_VERSION = '0.53.0';
6340
+ const src_OXLINT_VERSION = '1.68.0';
6341
+ const src_POSTCSS_VERSION = '^8.5.15';
6342
+ const src_ULTRACITE_VERSION = '7.8.1';
6343
+ const TYPES_REACT_VERSION = '^19.2.17';
6344
+ const TYPES_REACT_DOM_VERSION = '^19.2.3';
6073
6345
  const requiredDeniedPaths = [
6074
6346
  '.git/**',
6075
6347
  '.npmrc',
@@ -6427,7 +6699,7 @@ function readCreatePackageJson() {
6427
6699
  return JSON.parse(node_fs.readFileSync(createPackageJson, 'utf-8'));
6428
6700
  }
6429
6701
  function isBleedingDevCreatePackage(createPackage) {
6430
- return '@bleedingdev/modern-js-create' === createPackage.name;
6702
+ return createPackage.name === BLEEDINGDEV_CREATE_PACKAGE;
6431
6703
  }
6432
6704
  function getBleedingDevFrameworkVersion(createPackage, fallbackVersion) {
6433
6705
  const frameworkVersion = createPackage.ultramodern?.frameworkVersion;
@@ -6534,71 +6806,109 @@ function detectUltramodernPackageSource(args, defaultPackageVersion, createPacka
6534
6806
  console.error('--ultramodern-package-source must be "workspace" or "install"');
6535
6807
  process.exit(1);
6536
6808
  }
6809
+ const packageSourceStrategy = strategy;
6810
+ const explicitRegistry = getOptionValue(args, [
6811
+ '--ultramodern-package-registry'
6812
+ ]);
6813
+ const aliasScope = getOptionValue(args, [
6814
+ '--ultramodern-package-scope'
6815
+ ]) ?? (bleedingDevDefaults && 'install' === packageSourceStrategy && !explicitRegistry ? BLEEDINGDEV_PACKAGE_SCOPE : void 0);
6537
6816
  return {
6538
- strategy,
6817
+ strategy: packageSourceStrategy,
6539
6818
  modernPackageVersion: getOptionValue(args, [
6540
6819
  '--ultramodern-package-version'
6541
6820
  ]) ?? defaultPackageVersion,
6542
- registry: getOptionValue(args, [
6543
- '--ultramodern-package-registry'
6544
- ]),
6545
- aliasScope: getOptionValue(args, [
6546
- '--ultramodern-package-scope'
6547
- ]) ?? (bleedingDevDefaults && 'install' === strategy ? 'bleedingdev' : void 0),
6821
+ registry: explicitRegistry,
6822
+ aliasScope,
6548
6823
  aliasPackageNamePrefix: getOptionValue(args, [
6549
6824
  '--ultramodern-package-name-prefix'
6550
- ]) ?? 'modern-js-'
6825
+ ]) ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
6551
6826
  };
6552
6827
  }
6553
- function src_modernAliasPackageName(packageName, packageSource) {
6554
- if (!packageSource.aliasScope) return packageName;
6555
- const scope = packageSource.aliasScope.replace(/^@/, '');
6556
- const unscopedName = packageName.split('/').at(-1);
6557
- return `@${scope}/${packageSource.aliasPackageNamePrefix ?? ''}${unscopedName}`;
6828
+ function hasExplicitUltramodernPackageSource(args, value) {
6829
+ const configuredValue = getOptionValue(args, [
6830
+ '--ultramodern-package-source'
6831
+ ]);
6832
+ return value ? configuredValue === value : void 0 !== configuredValue;
6558
6833
  }
6559
- function singleAppModernPackageSpecifier(packageName, packageSource, useWorkspaceProtocol) {
6560
- if (useWorkspaceProtocol) return 'workspace:*';
6561
- if ('install' !== packageSource.strategy || !packageSource.aliasScope) return packageSource.modernPackageVersion;
6562
- return `npm:${src_modernAliasPackageName(packageName, packageSource)}@${packageSource.modernPackageVersion}`;
6834
+ function readBleedingDevFrameworkVersionFromRegistry() {
6835
+ const envVersion = process.env[BLEEDINGDEV_FRAMEWORK_VERSION_ENV]?.trim();
6836
+ if (envVersion) {
6837
+ if (!semverPattern.test(envVersion)) {
6838
+ console.error(`${BLEEDINGDEV_FRAMEWORK_VERSION_ENV} must be a valid semver version`);
6839
+ process.exit(1);
6840
+ }
6841
+ return envVersion;
6842
+ }
6843
+ try {
6844
+ const rawVersion = runSetupCommand('npm', [
6845
+ 'view',
6846
+ `${BLEEDINGDEV_CREATE_PACKAGE}@latest`,
6847
+ 'ultramodern.frameworkVersion',
6848
+ '--json'
6849
+ ]).trim();
6850
+ const version = JSON.parse(rawVersion);
6851
+ if ('string' == typeof version && semverPattern.test(version)) return version;
6852
+ } catch {}
6853
+ console.error([
6854
+ `Could not resolve ${BLEEDINGDEV_CREATE_PACKAGE}@latest ultramodern.frameworkVersion.`,
6855
+ 'Pass --workspace to use local workspace protocol dependencies,',
6856
+ 'or pass --ultramodern-package-version with the exact BleedingDev framework cohort.'
6857
+ ].join(' '));
6858
+ process.exit(1);
6563
6859
  }
6564
- const singleAppModernPackages = [
6565
- '@modern-js/runtime',
6566
- '@modern-js/app-tools',
6567
- '@modern-js/tsconfig',
6568
- '@modern-js/plugin-i18n',
6569
- '@modern-js/plugin-tanstack',
6570
- '@modern-js/plugin-bff',
6571
- '@modern-js/adapter-rstest'
6572
- ];
6573
- function createSingleAppPackageSourceEvidence(packageSource, useWorkspaceProtocol) {
6574
- const strategy = useWorkspaceProtocol ? 'workspace' : 'install';
6575
- const specifier = useWorkspaceProtocol ? 'workspace:*' : packageSource.modernPackageVersion;
6576
- const aliases = 'install' === strategy && packageSource.aliasScope ? Object.fromEntries(singleAppModernPackages.map((packageName)=>[
6577
- packageName,
6578
- src_modernAliasPackageName(packageName, packageSource)
6579
- ])) : void 0;
6860
+ function resolveInstallBackedPackageSource(args, createPackage, packageSource) {
6861
+ const explicitVersion = getOptionValue(args, [
6862
+ '--ultramodern-package-version'
6863
+ ]);
6864
+ const explicitRegistry = getOptionValue(args, [
6865
+ '--ultramodern-package-registry'
6866
+ ]);
6867
+ const aliasScope = getOptionValue(args, [
6868
+ '--ultramodern-package-scope'
6869
+ ]) ?? packageSource.aliasScope ?? (explicitRegistry ? void 0 : BLEEDINGDEV_PACKAGE_SCOPE);
6870
+ return {
6871
+ ...packageSource,
6872
+ strategy: 'install',
6873
+ modernPackageVersion: explicitVersion ?? (isBleedingDevCreatePackage(createPackage) ? packageSource.modernPackageVersion : readBleedingDevFrameworkVersionFromRegistry()),
6874
+ aliasScope,
6875
+ aliasPackageNamePrefix: getOptionValue(args, [
6876
+ '--ultramodern-package-name-prefix'
6877
+ ]) ?? packageSource.aliasPackageNamePrefix ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
6878
+ };
6879
+ }
6880
+ function resolveSingleAppPackageSource(args, createPackage, packageSource, useWorkspaceProtocol) {
6881
+ if (useWorkspaceProtocol) return {
6882
+ ...packageSource,
6883
+ strategy: 'workspace',
6884
+ modernPackageVersion: WORKSPACE_PACKAGE_VERSION
6885
+ };
6886
+ return resolveInstallBackedPackageSource(args, createPackage, packageSource);
6887
+ }
6888
+ function resolveWorkspacePackageSource(args, createPackage, packageSource) {
6889
+ if (hasExplicitUltramodernPackageSource(args, 'workspace')) return {
6890
+ ...packageSource,
6891
+ strategy: 'workspace',
6892
+ modernPackageVersion: WORKSPACE_PACKAGE_VERSION
6893
+ };
6894
+ return resolveInstallBackedPackageSource(args, createPackage, packageSource);
6895
+ }
6896
+ function createSingleAppPackageSourceEvidence(packageSource) {
6580
6897
  return {
6581
6898
  schemaVersion: 1,
6582
6899
  preset: 'presetUltramodern',
6583
- strategy,
6584
- modernPackages: {
6585
- specifier,
6586
- packages: singleAppModernPackages,
6587
- ...packageSource.registry ? {
6588
- registry: packageSource.registry
6589
- } : {},
6590
- ...aliases ? {
6591
- aliases
6592
- } : {}
6593
- }
6900
+ strategy: packageSource.strategy,
6901
+ modernPackages: createModernPackagesMetadata(ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES, packageSource, {
6902
+ includeAliases: 'install' === packageSource.strategy
6903
+ })
6594
6904
  };
6595
6905
  }
6596
- function writeSingleAppPackageSourceEvidence(targetDir, packageSource, useWorkspaceProtocol) {
6906
+ function writeSingleAppPackageSourceEvidence(targetDir, packageSource) {
6597
6907
  const evidencePath = node_path.join(targetDir, '.modernjs', 'ultramodern-package-source.json');
6598
6908
  node_fs.mkdirSync(node_path.dirname(evidencePath), {
6599
6909
  recursive: true
6600
6910
  });
6601
- node_fs.writeFileSync(evidencePath, `${JSON.stringify(createSingleAppPackageSourceEvidence(packageSource, useWorkspaceProtocol), null, 2)}\n`);
6911
+ node_fs.writeFileSync(evidencePath, `${JSON.stringify(createSingleAppPackageSourceEvidence(packageSource), null, 2)}\n`);
6602
6912
  }
6603
6913
  function runSetupCommand(command, args, options = {}) {
6604
6914
  return execFileSync(command, args, {
@@ -6803,12 +7113,13 @@ async function main() {
6803
7113
  }
6804
7114
  const generateWorkspace = detectUltramodernWorkspaceFlag();
6805
7115
  if (generateWorkspace) {
7116
+ const packageSource = resolveWorkspacePackageSource(args, createPackage, detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage));
6806
7117
  generateUltramodernWorkspace({
6807
7118
  targetDir,
6808
7119
  packageName: generatedPackageName,
6809
7120
  modernVersion: version,
6810
7121
  enableTailwind: detectTailwindFlag(),
6811
- packageSource: detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage)
7122
+ packageSource
6812
7123
  });
6813
7124
  initializeGeneratedGitRepository(targetDir);
6814
7125
  const dim = '\x1b[2m\x1b[3m';
@@ -6829,20 +7140,34 @@ async function main() {
6829
7140
  const bffRuntime = detectBffRuntime();
6830
7141
  const enableTailwind = detectTailwindFlag();
6831
7142
  const useWorkspaceProtocol = detectWorkspaceProtocolFlag();
6832
- const packageSource = detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage);
6833
- const templateManifest = createBuiltinTemplateManifest(version);
7143
+ const packageSource = resolveSingleAppPackageSource(args, createPackage, detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage), useWorkspaceProtocol);
7144
+ const templateManifest = createBuiltinTemplateManifest('install' === packageSource.strategy ? packageSource.modernPackageVersion : version);
6834
7145
  validateTemplateManifest(templateManifest);
6835
7146
  copyTemplate(templateDir, targetDir, {
6836
7147
  packageName: generatedPackageName,
6837
- version: useWorkspaceProtocol ? 'workspace:*' : packageSource.modernPackageVersion,
6838
- runtimeVersion: singleAppModernPackageSpecifier('@modern-js/runtime', packageSource, useWorkspaceProtocol),
6839
- appToolsVersion: singleAppModernPackageSpecifier('@modern-js/app-tools', packageSource, useWorkspaceProtocol),
6840
- adapterRstestVersion: singleAppModernPackageSpecifier('@modern-js/adapter-rstest', packageSource, useWorkspaceProtocol),
6841
- tsconfigVersion: singleAppModernPackageSpecifier('@modern-js/tsconfig', packageSource, useWorkspaceProtocol),
6842
- pluginTanstackVersion: singleAppModernPackageSpecifier('@modern-js/plugin-tanstack', packageSource, useWorkspaceProtocol),
6843
- pluginBffVersion: singleAppModernPackageSpecifier('@modern-js/plugin-bff', packageSource, useWorkspaceProtocol),
6844
- pluginI18nVersion: singleAppModernPackageSpecifier('@modern-js/plugin-i18n', packageSource, useWorkspaceProtocol),
7148
+ version: 'workspace' === packageSource.strategy ? WORKSPACE_PACKAGE_VERSION : packageSource.modernPackageVersion,
7149
+ runtimeVersion: modernPackageSpecifier('@modern-js/runtime', packageSource),
7150
+ appToolsVersion: modernPackageSpecifier('@modern-js/app-tools', packageSource),
7151
+ adapterRstestVersion: modernPackageSpecifier('@modern-js/adapter-rstest', packageSource),
7152
+ tsconfigVersion: modernPackageSpecifier('@modern-js/tsconfig', packageSource),
7153
+ pluginTanstackVersion: modernPackageSpecifier('@modern-js/plugin-tanstack', packageSource),
7154
+ pluginBffVersion: modernPackageSpecifier('@modern-js/plugin-bff', packageSource),
7155
+ pluginI18nVersion: modernPackageSpecifier('@modern-js/plugin-i18n', packageSource),
6845
7156
  tanstackRouterVersion: src_TANSTACK_ROUTER_VERSION,
7157
+ i18nextVersion: src_I18NEXT_VERSION,
7158
+ reactVersion: src_REACT_VERSION,
7159
+ reactDomVersion: src_REACT_DOM_VERSION,
7160
+ reactI18nextVersion: REACT_I18NEXT_VERSION,
7161
+ effectTsgoVersion: src_EFFECT_TSGO_VERSION,
7162
+ typescriptNativePreviewVersion: src_TYPESCRIPT_NATIVE_PREVIEW_VERSION,
7163
+ rstestCoreVersion: RSTEST_CORE_VERSION,
7164
+ happyDomVersion: HAPPY_DOM_VERSION,
7165
+ oxfmtVersion: src_OXFMT_VERSION,
7166
+ oxlintVersion: src_OXLINT_VERSION,
7167
+ postcssVersion: src_POSTCSS_VERSION,
7168
+ ultraciteVersion: src_ULTRACITE_VERSION,
7169
+ typesReactVersion: TYPES_REACT_VERSION,
7170
+ typesReactDomVersion: TYPES_REACT_DOM_VERSION,
6846
7171
  tailwindVersion: src_TAILWIND_VERSION,
6847
7172
  tailwindPostcssVersion: src_TAILWIND_POSTCSS_VERSION,
6848
7173
  pnpmVersion: src_PNPM_VERSION,
@@ -6859,7 +7184,7 @@ async function main() {
6859
7184
  ...packageJson.modernjs ?? {},
6860
7185
  preset: 'presetUltramodern',
6861
7186
  packageSource: {
6862
- strategy: useWorkspaceProtocol ? 'workspace' : 'install',
7187
+ strategy: packageSource.strategy,
6863
7188
  config: './.modernjs/ultramodern-package-source.json'
6864
7189
  }
6865
7190
  };
@@ -6894,7 +7219,7 @@ async function main() {
6894
7219
  }
6895
7220
  node_fs.writeFileSync(targetPackageJson, `${JSON.stringify(packageJson, null, 2)}\n`);
6896
7221
  writeTemplateManifestEvidence(targetDir, templateManifest);
6897
- writeSingleAppPackageSourceEvidence(targetDir, packageSource, useWorkspaceProtocol);
7222
+ writeSingleAppPackageSourceEvidence(targetDir, packageSource);
6898
7223
  if (!isSubproject) initializeGeneratedGitRepository(targetDir);
6899
7224
  const dim = '\x1b[2m\x1b[3m';
6900
7225
  const reset = '\x1b[0m';
@@ -6948,6 +7273,20 @@ function copyTemplate(src, dest, options) {
6948
7273
  pluginBffVersion: options.pluginBffVersion,
6949
7274
  pluginI18nVersion: options.pluginI18nVersion,
6950
7275
  tanstackRouterVersion: options.tanstackRouterVersion,
7276
+ i18nextVersion: options.i18nextVersion,
7277
+ reactVersion: options.reactVersion,
7278
+ reactDomVersion: options.reactDomVersion,
7279
+ reactI18nextVersion: options.reactI18nextVersion,
7280
+ effectTsgoVersion: options.effectTsgoVersion,
7281
+ typescriptNativePreviewVersion: options.typescriptNativePreviewVersion,
7282
+ rstestCoreVersion: options.rstestCoreVersion,
7283
+ happyDomVersion: options.happyDomVersion,
7284
+ oxfmtVersion: options.oxfmtVersion,
7285
+ oxlintVersion: options.oxlintVersion,
7286
+ postcssVersion: options.postcssVersion,
7287
+ ultraciteVersion: options.ultraciteVersion,
7288
+ typesReactVersion: options.typesReactVersion,
7289
+ typesReactDomVersion: options.typesReactDomVersion,
6951
7290
  tailwindVersion: options.tailwindVersion,
6952
7291
  tailwindPostcssVersion: options.tailwindPostcssVersion,
6953
7292
  pnpmVersion: options.pnpmVersion,