@bleedingdev/modern-js-create 3.4.0-ultramodern.17 → 3.4.0-ultramodern.19

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.
@@ -69,6 +69,12 @@ function createAppModernConfig(scope, app) {
69
69
  },
70
70
  ` : '';
71
71
  const bffPluginEntry = (0, external_descriptors_cjs_namespaceObject.appHasEffectApi)(app) ? ' bffPlugin(),\n' : '';
72
+ const defaultAssetPrefixSource = 'shell' === app.kind ? "const defaultAssetPrefix = '/';" : `const remoteAssetOrigin =
73
+ configuredCloudflareUrl ||
74
+ inferredCloudflareUrl ||
75
+ (cloudflareDeployEnabled ? '/' : \`http://localhost:\${port}\`);
76
+ const defaultRemoteAssetPrefix = \`\${remoteAssetOrigin.replace(/\\/+$/u, '')}/\`;
77
+ const defaultAssetPrefix = defaultRemoteAssetPrefix;`;
72
78
  return `// @effect-diagnostics processEnv:off
73
79
  import {
74
80
  appTools,
@@ -131,12 +137,12 @@ const siteUrl =
131
137
  configuredCloudflareUrl ||
132
138
  inferredCloudflareUrl ||
133
139
  \`http://localhost:\${port}\`;
134
- // Asset loading is intentionally independent from the canonical site URL and
135
- // deployment public URL. Without an explicit asset prefix, assets stay
136
- // origin-relative so self-hosted apps, tunnels, and reverse proxies never leak
137
- // localhost URLs into production HTML.
140
+ ${defaultAssetPrefixSource}
141
+ // Asset loading is intentionally independent from the canonical site URL.
142
+ // Module Federation remotes must publish an absolute publicPath so browsers
143
+ // load remoteEntry.js and exposed chunks from the remote origin, not the host.
138
144
  const assetPrefix =
139
- configuredModernAssetPrefix || configuredUltramodernAssetPrefix || '/';
145
+ configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix;
140
146
 
141
147
  if (
142
148
  cloudflareDeployEnabled &&
@@ -141,7 +141,8 @@ function appDependencies(scope, packageSource, app, remotes = [], bridge) {
141
141
  [(0, external_naming_cjs_namespaceObject.packageName)(scope, 'shared-design-tokens')]: external_ultramodern_package_source_cjs_namespaceObject.WORKSPACE_PACKAGE_VERSION,
142
142
  react: external_versions_cjs_namespaceObject.REACT_VERSION,
143
143
  'react-dom': external_versions_cjs_namespaceObject.REACT_DOM_VERSION,
144
- 'react-router': external_versions_cjs_namespaceObject.REACT_ROUTER_VERSION
144
+ 'react-router': external_versions_cjs_namespaceObject.REACT_ROUTER_VERSION,
145
+ 'react-router-dom': external_versions_cjs_namespaceObject.REACT_ROUTER_VERSION
145
146
  };
146
147
  for (const dependency of bridge?.dependencies ?? [])dependencies[dependency] = external_ultramodern_package_source_cjs_namespaceObject.WORKSPACE_PACKAGE_VERSION;
147
148
  if ('shell' === app.kind) {
@@ -148,7 +148,7 @@ const PUBLIC_WEBSITE_POLICY = {
148
148
  requireWebManifestWhenPresent: true
149
149
  },
150
150
  statusCodes: {
151
- notFoundRoute: '/__ultramodern-smoke-missing',
151
+ notFoundRoute: '/__ultramodern-smoke-missing/nope',
152
152
  unknownRouteStatus: 404
153
153
  },
154
154
  indexing: {
@@ -18,6 +18,12 @@ function createAppModernConfig(scope, app) {
18
18
  },
19
19
  ` : '';
20
20
  const bffPluginEntry = appHasEffectApi(app) ? ' bffPlugin(),\n' : '';
21
+ const defaultAssetPrefixSource = 'shell' === app.kind ? "const defaultAssetPrefix = '/';" : `const remoteAssetOrigin =
22
+ configuredCloudflareUrl ||
23
+ inferredCloudflareUrl ||
24
+ (cloudflareDeployEnabled ? '/' : \`http://localhost:\${port}\`);
25
+ const defaultRemoteAssetPrefix = \`\${remoteAssetOrigin.replace(/\\/+$/u, '')}/\`;
26
+ const defaultAssetPrefix = defaultRemoteAssetPrefix;`;
21
27
  return `// @effect-diagnostics processEnv:off
22
28
  import {
23
29
  appTools,
@@ -80,12 +86,12 @@ const siteUrl =
80
86
  configuredCloudflareUrl ||
81
87
  inferredCloudflareUrl ||
82
88
  \`http://localhost:\${port}\`;
83
- // Asset loading is intentionally independent from the canonical site URL and
84
- // deployment public URL. Without an explicit asset prefix, assets stay
85
- // origin-relative so self-hosted apps, tunnels, and reverse proxies never leak
86
- // localhost URLs into production HTML.
89
+ ${defaultAssetPrefixSource}
90
+ // Asset loading is intentionally independent from the canonical site URL.
91
+ // Module Federation remotes must publish an absolute publicPath so browsers
92
+ // load remoteEntry.js and exposed chunks from the remote origin, not the host.
87
93
  const assetPrefix =
88
- configuredModernAssetPrefix || configuredUltramodernAssetPrefix || '/';
94
+ configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix;
89
95
 
90
96
  if (
91
97
  cloudflareDeployEnabled &&
@@ -95,7 +95,8 @@ function appDependencies(scope, packageSource, app, remotes = [], bridge) {
95
95
  [packageName(scope, 'shared-design-tokens')]: WORKSPACE_PACKAGE_VERSION,
96
96
  react: REACT_VERSION,
97
97
  'react-dom': REACT_DOM_VERSION,
98
- 'react-router': REACT_ROUTER_VERSION
98
+ 'react-router': REACT_ROUTER_VERSION,
99
+ 'react-router-dom': REACT_ROUTER_VERSION
99
100
  };
100
101
  for (const dependency of bridge?.dependencies ?? [])dependencies[dependency] = WORKSPACE_PACKAGE_VERSION;
101
102
  if ('shell' === app.kind) {
@@ -107,7 +107,7 @@ const PUBLIC_WEBSITE_POLICY = {
107
107
  requireWebManifestWhenPresent: true
108
108
  },
109
109
  statusCodes: {
110
- notFoundRoute: '/__ultramodern-smoke-missing',
110
+ notFoundRoute: '/__ultramodern-smoke-missing/nope',
111
111
  unknownRouteStatus: 404
112
112
  },
113
113
  indexing: {
@@ -19,6 +19,12 @@ function createAppModernConfig(scope, app) {
19
19
  },
20
20
  ` : '';
21
21
  const bffPluginEntry = appHasEffectApi(app) ? ' bffPlugin(),\n' : '';
22
+ const defaultAssetPrefixSource = 'shell' === app.kind ? "const defaultAssetPrefix = '/';" : `const remoteAssetOrigin =
23
+ configuredCloudflareUrl ||
24
+ inferredCloudflareUrl ||
25
+ (cloudflareDeployEnabled ? '/' : \`http://localhost:\${port}\`);
26
+ const defaultRemoteAssetPrefix = \`\${remoteAssetOrigin.replace(/\\/+$/u, '')}/\`;
27
+ const defaultAssetPrefix = defaultRemoteAssetPrefix;`;
22
28
  return `// @effect-diagnostics processEnv:off
23
29
  import {
24
30
  appTools,
@@ -81,12 +87,12 @@ const siteUrl =
81
87
  configuredCloudflareUrl ||
82
88
  inferredCloudflareUrl ||
83
89
  \`http://localhost:\${port}\`;
84
- // Asset loading is intentionally independent from the canonical site URL and
85
- // deployment public URL. Without an explicit asset prefix, assets stay
86
- // origin-relative so self-hosted apps, tunnels, and reverse proxies never leak
87
- // localhost URLs into production HTML.
90
+ ${defaultAssetPrefixSource}
91
+ // Asset loading is intentionally independent from the canonical site URL.
92
+ // Module Federation remotes must publish an absolute publicPath so browsers
93
+ // load remoteEntry.js and exposed chunks from the remote origin, not the host.
88
94
  const assetPrefix =
89
- configuredModernAssetPrefix || configuredUltramodernAssetPrefix || '/';
95
+ configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix;
90
96
 
91
97
  if (
92
98
  cloudflareDeployEnabled &&
@@ -96,7 +96,8 @@ function appDependencies(scope, packageSource, app, remotes = [], bridge) {
96
96
  [packageName(scope, 'shared-design-tokens')]: WORKSPACE_PACKAGE_VERSION,
97
97
  react: REACT_VERSION,
98
98
  'react-dom': REACT_DOM_VERSION,
99
- 'react-router': REACT_ROUTER_VERSION
99
+ 'react-router': REACT_ROUTER_VERSION,
100
+ 'react-router-dom': REACT_ROUTER_VERSION
100
101
  };
101
102
  for (const dependency of bridge?.dependencies ?? [])dependencies[dependency] = WORKSPACE_PACKAGE_VERSION;
102
103
  if ('shell' === app.kind) {
@@ -108,7 +108,7 @@ const PUBLIC_WEBSITE_POLICY = {
108
108
  requireWebManifestWhenPresent: true
109
109
  },
110
110
  statusCodes: {
111
- notFoundRoute: '/__ultramodern-smoke-missing',
111
+ notFoundRoute: '/__ultramodern-smoke-missing/nope',
112
112
  unknownRouteStatus: 404
113
113
  },
114
114
  indexing: {
package/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "engines": {
22
22
  "node": ">=20"
23
23
  },
24
- "version": "3.4.0-ultramodern.17",
24
+ "version": "3.4.0-ultramodern.19",
25
25
  "types": "./dist/types/index.d.ts",
26
26
  "main": "./dist/esm-node/index.js",
27
27
  "bin": {
@@ -77,7 +77,7 @@
77
77
  "@modern-js/codesmith": "2.6.9",
78
78
  "oxfmt": "0.55.0",
79
79
  "ultracite": "7.8.3",
80
- "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.4.0-ultramodern.17"
80
+ "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.4.0-ultramodern.19"
81
81
  },
82
82
  "devDependencies": {
83
83
  "@rslib/core": "0.23.0",
@@ -99,6 +99,6 @@
99
99
  "test": "rm -rf dist && rslib build -c rslibconfig.mts && rstest --passWithNoTests"
100
100
  },
101
101
  "ultramodern": {
102
- "frameworkVersion": "3.4.0-ultramodern.17"
102
+ "frameworkVersion": "3.4.0-ultramodern.19"
103
103
  }
104
104
  }
@@ -166,7 +166,7 @@ function createQualityGates() {
166
166
  requireWebManifestWhenPresent: true,
167
167
  },
168
168
  statusCodes: {
169
- notFoundRoute: '/__ultramodern-smoke-missing',
169
+ notFoundRoute: '/__ultramodern-smoke-missing/nope',
170
170
  unknownRouteStatus: 404,
171
171
  },
172
172
  indexing: {
@@ -478,7 +478,8 @@ async function validateSsrHead(evidence, app, publicUrl, ssrRoute, ssr) {
478
478
  async function validateNotFound(evidence, app, publicUrl) {
479
479
  const qualityGates = app.deploy?.cloudflare?.qualityGates ?? {};
480
480
  const notFoundRoute =
481
- qualityGates.statusCodes?.notFoundRoute ?? '/__ultramodern-smoke-missing';
481
+ qualityGates.statusCodes?.notFoundRoute ??
482
+ '/__ultramodern-smoke-missing/nope';
482
483
  const expectedStatus = qualityGates.statusCodes?.unknownRouteStatus ?? 404;
483
484
  const response = await fetchText(joinUrl(publicUrl, notFoundRoute));
484
485
  evidence.assertions.push({
@@ -353,7 +353,7 @@ const createQualityGates = () => ({
353
353
  requireWebManifestWhenPresent: true,
354
354
  },
355
355
  statusCodes: {
356
- notFoundRoute: '/__ultramodern-smoke-missing',
356
+ notFoundRoute: '/__ultramodern-smoke-missing/nope',
357
357
  unknownRouteStatus: 404,
358
358
  },
359
359
  indexing: {
@@ -480,7 +480,7 @@ const createAppConfigContract = app => ({
480
480
  output: {
481
481
  assetPrefix: {
482
482
  envFallbackOrder: ['MODERN_ASSET_PREFIX', 'ULTRAMODERN_ASSET_PREFIX'],
483
- default: '/',
483
+ default: app.kind === 'shell' ? '/' : 'app-public-origin',
484
484
  },
485
485
  disableTsChecker: false,
486
486
  },
@@ -1790,8 +1790,9 @@ assert(shellModernConfig.includes('name: cloudflareWorkerName'), 'Shell modern.c
1790
1790
  assert(shellModernConfig.includes('const assetPrefix ='), 'Shell modern.config.ts must derive a dedicated asset prefix');
1791
1791
  assert(shellModernConfig.includes("const configuredUltramodernAssetPrefix = envValue('ULTRAMODERN_ASSET_PREFIX')"), 'Shell asset prefix must support ULTRAMODERN_ASSET_PREFIX');
1792
1792
  assert(shellModernConfig.includes("const configuredModernAssetPrefix = envValue('MODERN_ASSET_PREFIX')"), 'Shell asset prefix must support MODERN_ASSET_PREFIX');
1793
+ assert(shellModernConfig.includes("const defaultAssetPrefix = '/'"), 'Shell asset prefix must default to origin-relative assets');
1793
1794
  const shellAssetPrefixExpression = extractAssetPrefixExpression(shellModernConfig);
1794
- assert(shellAssetPrefixExpression.includes("configuredModernAssetPrefix || configuredUltramodernAssetPrefix || '/'"), 'Shell asset prefix fallback order is incorrect');
1795
+ assert(shellAssetPrefixExpression.includes("configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix"), 'Shell asset prefix fallback order is incorrect');
1795
1796
  assert(!shellAssetPrefixExpression.includes('configuredSiteUrl') && !shellAssetPrefixExpression.includes('MODERN_PUBLIC_SITE_URL'), 'Shell asset prefix must not fall back to MODERN_PUBLIC_SITE_URL');
1796
1797
  assert(!shellAssetPrefixExpression.includes('configuredCloudflareUrl') && !shellAssetPrefixExpression.includes('ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP'), 'Shell asset prefix must not fall back to the per-app public URL');
1797
1798
  assert(!shellAssetPrefixExpression.includes('inferredCloudflareUrl') && !shellAssetPrefixExpression.includes('ULTRAMODERN_CLOUDFLARE_WORKERS_DEV_SUBDOMAIN'), 'Shell asset prefix must not infer workers.dev URLs');
@@ -1889,15 +1890,17 @@ for (const vertical of fullStackVerticals) {
1889
1890
  assert(modernConfig.includes('const assetPrefix ='), `${vertical.id} modern.config.ts must derive a dedicated asset prefix`);
1890
1891
  assert(modernConfig.includes("const configuredUltramodernAssetPrefix = envValue('ULTRAMODERN_ASSET_PREFIX')"), `${vertical.id} asset prefix must support ULTRAMODERN_ASSET_PREFIX`);
1891
1892
  assert(modernConfig.includes("const configuredModernAssetPrefix = envValue('MODERN_ASSET_PREFIX')"), `${vertical.id} asset prefix must support MODERN_ASSET_PREFIX`);
1893
+ assert(modernConfig.includes('const defaultRemoteAssetPrefix'), `${vertical.id} asset prefix must derive the remote asset origin`);
1894
+ assert(modernConfig.includes('const defaultAssetPrefix = defaultRemoteAssetPrefix'), `${vertical.id} asset prefix must default to its own remote origin`);
1892
1895
  const verticalAssetPrefixExpression = extractAssetPrefixExpression(modernConfig);
1893
- assert(verticalAssetPrefixExpression.includes("configuredModernAssetPrefix || configuredUltramodernAssetPrefix || '/'"), `${vertical.id} asset prefix fallback order is incorrect`);
1896
+ assert(verticalAssetPrefixExpression.includes("configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix"), `${vertical.id} asset prefix fallback order is incorrect`);
1894
1897
  assert(!verticalAssetPrefixExpression.includes('configuredSiteUrl') && !verticalAssetPrefixExpression.includes('MODERN_PUBLIC_SITE_URL'), `${vertical.id} asset prefix must not fall back to MODERN_PUBLIC_SITE_URL`);
1895
- assert(!verticalAssetPrefixExpression.includes('configuredCloudflareUrl') && !verticalAssetPrefixExpression.includes(`ULTRAMODERN_PUBLIC_URL_${vertical.id.replace(/-/g, '_').toUpperCase()}`), `${vertical.id} asset prefix must not fall back to the per-app public URL`);
1896
- assert(!verticalAssetPrefixExpression.includes('inferredCloudflareUrl') && !verticalAssetPrefixExpression.includes('ULTRAMODERN_CLOUDFLARE_WORKERS_DEV_SUBDOMAIN'), `${vertical.id} asset prefix must not infer workers.dev URLs`);
1898
+ assert(modernConfig.includes(`envValue('ULTRAMODERN_PUBLIC_URL_${vertical.id.replace(/-/g, '_').toUpperCase()}')`), `${vertical.id} asset prefix must read its per-app public URL`);
1899
+ assert(modernConfig.includes('inferredCloudflareUrl'), `${vertical.id} asset prefix must support workers.dev origin inference`);
1897
1900
  assert(modernConfig.includes("assetPrefix: '/'"), `${vertical.id} modern.config.ts must keep dev assets origin-relative`);
1898
1901
  assert(modernConfig.includes('assetPrefix,'), `${vertical.id} modern.config.ts must wire output.assetPrefix to the derived asset prefix`);
1899
1902
  assert(contractEntry?.config?.dev?.assetPrefix === '/', `${vertical.id} dev asset prefix must stay origin-relative`);
1900
- assert(contractEntry?.config?.output?.assetPrefix?.default === '/', `${vertical.id} asset prefix must default to origin-relative paths`);
1903
+ assert(contractEntry?.config?.output?.assetPrefix?.default === 'app-public-origin', `${vertical.id} asset prefix must default to its app public origin`);
1901
1904
  assert(JSON.stringify(contractEntry?.config?.output?.assetPrefix?.envFallbackOrder) === JSON.stringify(['MODERN_ASSET_PREFIX', 'ULTRAMODERN_ASSET_PREFIX']), `${vertical.id} asset prefix env fallback order is incorrect`);
1902
1905
  assert(contractEntry?.config?.output?.disableTsChecker === false, `${vertical.id} must keep the framework TypeScript checker enabled`);
1903
1906
  assert(contractEntry?.config?.performance?.readinessDiagnostics?.default === 'enabled', `${vertical.id} performance readiness diagnostics must be default-on`);