@bleedingdev/modern-js-create 3.5.0-ultramodern.2 → 3.5.0-ultramodern.20
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/README.md +20 -14
- package/dist/cjs/ultramodern-tooling/commands.cjs +357 -3
- package/dist/cjs/ultramodern-workspace/app-files.cjs +8 -11
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +13 -6
- package/dist/cjs/ultramodern-workspace/package-json.cjs +15 -8
- package/dist/cjs/ultramodern-workspace/versions.cjs +5 -0
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +2 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +2 -0
- package/dist/esm/ultramodern-tooling/commands.js +357 -3
- package/dist/esm/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm/ultramodern-workspace/module-federation.js +13 -6
- package/dist/esm/ultramodern-workspace/package-json.js +5 -8
- package/dist/esm/ultramodern-workspace/versions.js +3 -1
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +3 -1
- package/dist/esm/ultramodern-workspace/write-workspace.js +3 -1
- package/dist/esm-node/ultramodern-tooling/commands.js +357 -3
- package/dist/esm-node/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm-node/ultramodern-workspace/module-federation.js +13 -6
- package/dist/esm-node/ultramodern-workspace/package-json.js +5 -8
- package/dist/esm-node/ultramodern-workspace/versions.js +3 -1
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +3 -1
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +3 -1
- package/dist/types/ultramodern-workspace/versions.d.ts +2 -0
- package/package.json +3 -3
- package/template-workspace/.gitignore.handlebars +3 -0
- package/template-workspace/README.md.handlebars +19 -13
- package/template-workspace/patches/@module-federation__bridge-react@2.6.0.patch +140 -0
- package/template-workspace/patches/@module-federation__modern-js-v3@2.6.0.patch +57 -0
- package/template-workspace/patches/drizzle-orm-ts7-strict-declarations.patch +452 -0
- package/template-workspace/patches/effect-schema-error-type-id.patch +18 -0
- package/template-workspace/pnpm-workspace.yaml.handlebars +8 -0
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +87 -5
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20"
|
|
23
23
|
},
|
|
24
|
-
"version": "3.5.0-ultramodern.
|
|
24
|
+
"version": "3.5.0-ultramodern.20",
|
|
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.56.0",
|
|
79
79
|
"ultracite": "7.8.3",
|
|
80
|
-
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.5.0-ultramodern.
|
|
80
|
+
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.5.0-ultramodern.20"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@rslib/core": "0.23.1",
|
|
@@ -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.5.0-ultramodern.
|
|
102
|
+
"frameworkVersion": "3.5.0-ultramodern.20"
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -117,19 +117,21 @@ regenerating or updating the workspace.
|
|
|
117
117
|
| `ULTRAMODERN_ASSET_PREFIX` | UltraModern compatibility asset prefix | Modern/Rspack-emitted asset URLs when `MODERN_ASSET_PREFIX` is unset |
|
|
118
118
|
| `ULTRAMODERN_PUBLIC_URL_<APP_ID>` | Per-app deployment/proof URL | Cloudflare proof inputs and Module Federation remote URLs |
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
`ULTRAMODERN_ASSET_PREFIX` → origin-relative `/`.
|
|
122
|
-
|
|
120
|
+
Shell asset URLs use this precedence: `MODERN_ASSET_PREFIX` →
|
|
121
|
+
`ULTRAMODERN_ASSET_PREFIX` → origin-relative `/`. Module Federation remotes use
|
|
122
|
+
the same env precedence, then fall back to their per-app public origin:
|
|
123
|
+
configured public URL, inferred workers.dev URL, or local dev port.
|
|
124
|
+
`MODERN_PUBLIC_SITE_URL` is canonical/SEO-only and must not be used as an
|
|
125
|
+
asset-prefix fallback.
|
|
123
126
|
SEO output uses `MODERN_PUBLIC_SITE_URL`; if it is unset, generated local and
|
|
124
127
|
preview outputs remain non-public until deployment proof provides explicit
|
|
125
128
|
public URLs.
|
|
126
129
|
|
|
127
|
-
Without public URLs configured, asset paths are origin-relative (`/`)
|
|
128
|
-
dev
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
from.
|
|
130
|
+
Without public URLs configured, shell asset paths are origin-relative (`/`).
|
|
131
|
+
Remote dev manifests publish their own local origin so host shells load
|
|
132
|
+
`remoteEntry.js` and exposed chunks from the remote dev server. Shell-only
|
|
133
|
+
workspaces can set `MODERN_PUBLIC_SITE_URL` for SEO output without changing
|
|
134
|
+
where assets load from.
|
|
133
135
|
|
|
134
136
|
## Cloudflare Proof
|
|
135
137
|
|
|
@@ -169,19 +171,23 @@ in API modules.
|
|
|
169
171
|
Generated pnpm overrides pin the framework-compatible Effect cohort. Keep
|
|
170
172
|
`effect` and `@effect/vitest` aligned with `pnpm-workspace.yaml`; do not add
|
|
171
173
|
new direct package-level Effect versions unless the whole UltraModern cohort is
|
|
172
|
-
upgraded.
|
|
174
|
+
upgraded. The generated pnpm policy intentionally excludes the matching
|
|
175
|
+
`effect` and `@effect/opentelemetry` cohort versions from the
|
|
176
|
+
minimum-release-age and no-downgrade checks while Effect's beta publishes move
|
|
177
|
+
from trusted-publisher metadata to provenance attestations.
|
|
173
178
|
|
|
174
179
|
For older generated workspaces, run the framework migration command first:
|
|
175
180
|
|
|
176
181
|
```bash
|
|
177
|
-
pnpm dlx @bleedingdev/modern-js-create@3.5.0-ultramodern.
|
|
178
|
-
migrate-strict-effect --version 3.5.0-ultramodern.
|
|
182
|
+
pnpm dlx @bleedingdev/modern-js-create@3.5.0-ultramodern.10 ultramodern \
|
|
183
|
+
migrate-strict-effect --version 3.5.0-ultramodern.10
|
|
179
184
|
pnpm api:check
|
|
180
185
|
pnpm contract:check
|
|
181
186
|
```
|
|
182
187
|
|
|
183
188
|
The command updates generated package-source metadata, Modern package aliases,
|
|
184
|
-
direct API topology metadata,
|
|
189
|
+
framework-owned toolchain pins, direct API topology metadata, strict Effect pnpm
|
|
190
|
+
overrides/trust policy, and the lockfile. Remaining failures are source
|
|
185
191
|
migration work; fix the owning API files instead of adding compatibility shims.
|
|
186
192
|
|
|
187
193
|
## Troubleshooting
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
diff --git a/dist/lazy-load-component-plugin-BYI941I2.mjs b/dist/lazy-load-component-plugin-BYI941I2.mjs
|
|
2
|
+
index dfba15be1e9753e0f164b53cfb22feda13f39ea4..6be1b47903b9f6807bb0111df6c588f0d54ebf53 100644
|
|
3
|
+
--- a/dist/lazy-load-component-plugin-BYI941I2.mjs
|
|
4
|
+
+++ b/dist/lazy-load-component-plugin-BYI941I2.mjs
|
|
5
|
+
@@ -235,6 +235,41 @@ function getTargetModuleInfo(id, instance) {
|
|
6
|
+
remoteEntry
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
+function normalizeHref(href) {
|
|
10
|
+
+ if (typeof document === "undefined") {
|
|
11
|
+
+ return href;
|
|
12
|
+
+ }
|
|
13
|
+
+ try {
|
|
14
|
+
+ return new URL(href, document.baseURI).href;
|
|
15
|
+
+ } catch {
|
|
16
|
+
+ return href;
|
|
17
|
+
+ }
|
|
18
|
+
+}
|
|
19
|
+
+function isStylesheetLink(link) {
|
|
20
|
+
+ return link.relList.contains("stylesheet") || link.rel.toLowerCase().split(/\s+/u).includes("stylesheet");
|
|
21
|
+
+}
|
|
22
|
+
+function hasStylesheetLinkInHead(href, ignoredLink) {
|
|
23
|
+
+ if (typeof document === "undefined" || !document.head) {
|
|
24
|
+
+ return false;
|
|
25
|
+
+ }
|
|
26
|
+
+ const normalizedHref = normalizeHref(href);
|
|
27
|
+
+ return Array.from(
|
|
28
|
+
+ document.head.querySelectorAll("link[href]")
|
|
29
|
+
+ ).some(
|
|
30
|
+
+ (link) => link !== ignoredLink && isStylesheetLink(link) && normalizeHref(link.href) === normalizedHref
|
|
31
|
+
+ );
|
|
32
|
+
+}
|
|
33
|
+
+function StylesheetAsset({ href }) {
|
|
34
|
+
+ const [shouldRender, setShouldRender] = useState(true);
|
|
35
|
+
+ const linkRef = useRef(null);
|
|
36
|
+
+ useEffect(() => {
|
|
37
|
+
+ setShouldRender(!hasStylesheetLinkInHead(href, linkRef.current));
|
|
38
|
+
+ }, [href]);
|
|
39
|
+
+ if (!shouldRender) {
|
|
40
|
+
+ return null;
|
|
41
|
+
+ }
|
|
42
|
+
+ return /* @__PURE__ */ React__default.createElement("link", { ref: linkRef, href, rel: "stylesheet", type: "text/css" });
|
|
43
|
+
+}
|
|
44
|
+
function collectSSRAssets(options) {
|
|
45
|
+
const {
|
|
46
|
+
id,
|
|
47
|
+
@@ -253,15 +288,19 @@ function collectSSRAssets(options) {
|
|
48
|
+
}
|
|
49
|
+
const { module: targetModule, publicPath, remoteEntry } = moduleAndPublicPath;
|
|
50
|
+
if (injectLink) {
|
|
51
|
+
+ const stylesheetHrefs = /* @__PURE__ */ new Set();
|
|
52
|
+
[...targetModule.assets.css.sync, ...targetModule.assets.css.async].sort().forEach((file, index) => {
|
|
53
|
+
+ const href = `${publicPath}${file}`;
|
|
54
|
+
+ if (stylesheetHrefs.has(href)) {
|
|
55
|
+
+ return;
|
|
56
|
+
+ }
|
|
57
|
+
+ stylesheetHrefs.add(href);
|
|
58
|
+
links.push(
|
|
59
|
+
/* @__PURE__ */ React__default.createElement(
|
|
60
|
+
- "link",
|
|
61
|
+
+ StylesheetAsset,
|
|
62
|
+
{
|
|
63
|
+
key: `${file.split(".")[0]}_${index}`,
|
|
64
|
+
- href: `${publicPath}${file}`,
|
|
65
|
+
- rel: "stylesheet",
|
|
66
|
+
- type: "text/css"
|
|
67
|
+
+ href
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
);
|
|
71
|
+
diff --git a/dist/lazy-load-component-plugin-DG4e3Tib.js b/dist/lazy-load-component-plugin-DG4e3Tib.js
|
|
72
|
+
index 321c9c3cd55bf9d62a6825c9186267dfe28e5e93..867e7237d5a2ea613130c7e1710cdd998924d9db 100644
|
|
73
|
+
--- a/dist/lazy-load-component-plugin-DG4e3Tib.js
|
|
74
|
+
+++ b/dist/lazy-load-component-plugin-DG4e3Tib.js
|
|
75
|
+
@@ -236,6 +236,41 @@ function getTargetModuleInfo(id, instance) {
|
|
76
|
+
remoteEntry
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
+function normalizeHref(href) {
|
|
80
|
+
+ if (typeof document === "undefined") {
|
|
81
|
+
+ return href;
|
|
82
|
+
+ }
|
|
83
|
+
+ try {
|
|
84
|
+
+ return new URL(href, document.baseURI).href;
|
|
85
|
+
+ } catch {
|
|
86
|
+
+ return href;
|
|
87
|
+
+ }
|
|
88
|
+
+}
|
|
89
|
+
+function isStylesheetLink(link) {
|
|
90
|
+
+ return link.relList.contains("stylesheet") || link.rel.toLowerCase().split(/\s+/u).includes("stylesheet");
|
|
91
|
+
+}
|
|
92
|
+
+function hasStylesheetLinkInHead(href, ignoredLink) {
|
|
93
|
+
+ if (typeof document === "undefined" || !document.head) {
|
|
94
|
+
+ return false;
|
|
95
|
+
+ }
|
|
96
|
+
+ const normalizedHref = normalizeHref(href);
|
|
97
|
+
+ return Array.from(
|
|
98
|
+
+ document.head.querySelectorAll("link[href]")
|
|
99
|
+
+ ).some(
|
|
100
|
+
+ (link) => link !== ignoredLink && isStylesheetLink(link) && normalizeHref(link.href) === normalizedHref
|
|
101
|
+
+ );
|
|
102
|
+
+}
|
|
103
|
+
+function StylesheetAsset({ href }) {
|
|
104
|
+
+ const [shouldRender, setShouldRender] = React.useState(true);
|
|
105
|
+
+ const linkRef = React.useRef(null);
|
|
106
|
+
+ React.useEffect(() => {
|
|
107
|
+
+ setShouldRender(!hasStylesheetLinkInHead(href, linkRef.current));
|
|
108
|
+
+ }, [href]);
|
|
109
|
+
+ if (!shouldRender) {
|
|
110
|
+
+ return null;
|
|
111
|
+
+ }
|
|
112
|
+
+ return /* @__PURE__ */ React.createElement("link", { ref: linkRef, href, rel: "stylesheet", type: "text/css" });
|
|
113
|
+
+}
|
|
114
|
+
function collectSSRAssets(options) {
|
|
115
|
+
const {
|
|
116
|
+
id,
|
|
117
|
+
@@ -254,15 +289,19 @@ function collectSSRAssets(options) {
|
|
118
|
+
}
|
|
119
|
+
const { module: targetModule, publicPath, remoteEntry } = moduleAndPublicPath;
|
|
120
|
+
if (injectLink) {
|
|
121
|
+
+ const stylesheetHrefs = /* @__PURE__ */ new Set();
|
|
122
|
+
[...targetModule.assets.css.sync, ...targetModule.assets.css.async].sort().forEach((file, index) => {
|
|
123
|
+
+ const href = `${publicPath}${file}`;
|
|
124
|
+
+ if (stylesheetHrefs.has(href)) {
|
|
125
|
+
+ return;
|
|
126
|
+
+ }
|
|
127
|
+
+ stylesheetHrefs.add(href);
|
|
128
|
+
links.push(
|
|
129
|
+
/* @__PURE__ */ React.createElement(
|
|
130
|
+
- "link",
|
|
131
|
+
+ StylesheetAsset,
|
|
132
|
+
{
|
|
133
|
+
key: `${file.split(".")[0]}_${index}`,
|
|
134
|
+
- href: `${publicPath}${file}`,
|
|
135
|
+
- rel: "stylesheet",
|
|
136
|
+
- type: "text/css"
|
|
137
|
+
+ href
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
diff --git a/dist/cjs/cli/configPlugin.js b/dist/cjs/cli/configPlugin.js
|
|
2
|
+
index 0d01ad0..e5485a2 100644
|
|
3
|
+
--- a/dist/cjs/cli/configPlugin.js
|
|
4
|
+
+++ b/dist/cjs/cli/configPlugin.js
|
|
5
|
+
@@ -212,9 +212,12 @@ var __webpack_exports__ = {};
|
|
6
|
+
if (!chain.output.get('uniqueName')) chain.output.uniqueName(mfConfig.name);
|
|
7
|
+
const splitChunkConfig = chain.optimization.splitChunks.entries();
|
|
8
|
+
if (!isServer) (0, utils_namespaceObject.autoDeleteSplitChunkCacheGroups)(mfConfig, splitChunkConfig);
|
|
9
|
+
- if (!isServer && enableSSR && splitChunkConfig && 'object' == typeof splitChunkConfig && splitChunkConfig.cacheGroups) {
|
|
10
|
+
+ if (!isServer && enableSSR && splitChunkConfig && 'object' == typeof splitChunkConfig && splitChunkConfig.cacheGroups && splitChunkConfig.chunks !== undefined && splitChunkConfig.chunks !== 'async') {
|
|
11
|
+
+ const previousChunks = splitChunkConfig.chunks;
|
|
12
|
+
splitChunkConfig.chunks = 'async';
|
|
13
|
+
- external_logger_js_default().warn('splitChunks.chunks = async is not allowed with stream SSR mode, it will auto changed to "async"');
|
|
14
|
+
+ if (void 0 !== previousChunks) {
|
|
15
|
+
+ external_logger_js_default().warn(`splitChunks.chunks = ${previousChunks} is not allowed with stream SSR mode, it will auto changed to "async"`);
|
|
16
|
+
+ }
|
|
17
|
+
}
|
|
18
|
+
if ((0, external_utils_js_namespaceObject.isDev)() && 'auto' === chain.output.get('publicPath')) {
|
|
19
|
+
var _modernjsConfig_server;
|
|
20
|
+
diff --git a/dist/esm/cli/configPlugin.mjs b/dist/esm/cli/configPlugin.mjs
|
|
21
|
+
index 3e880c8..93e4290 100644
|
|
22
|
+
--- a/dist/esm/cli/configPlugin.mjs
|
|
23
|
+
+++ b/dist/esm/cli/configPlugin.mjs
|
|
24
|
+
@@ -194,9 +194,12 @@ function patchBundlerConfig(options) {
|
|
25
|
+
if (!chain.output.get('uniqueName')) chain.output.uniqueName(mfConfig.name);
|
|
26
|
+
var splitChunkConfig = chain.optimization.splitChunks.entries();
|
|
27
|
+
if (!isServer) autoDeleteSplitChunkCacheGroups(mfConfig, splitChunkConfig);
|
|
28
|
+
- if (!isServer && enableSSR && splitChunkConfig && (void 0 === splitChunkConfig ? "undefined" : _type_of__(splitChunkConfig)) === 'object' && splitChunkConfig.cacheGroups) {
|
|
29
|
+
+ if (!isServer && enableSSR && splitChunkConfig && (void 0 === splitChunkConfig ? "undefined" : _type_of__(splitChunkConfig)) === 'object' && splitChunkConfig.cacheGroups && void 0 !== splitChunkConfig.chunks && splitChunkConfig.chunks !== 'async') {
|
|
30
|
+
+ var previousChunks = splitChunkConfig.chunks;
|
|
31
|
+
splitChunkConfig.chunks = 'async';
|
|
32
|
+
- logger.warn('splitChunks.chunks = async is not allowed with stream SSR mode, it will auto changed to "async"');
|
|
33
|
+
+ if (void 0 !== previousChunks) {
|
|
34
|
+
+ logger.warn("splitChunks.chunks = ".concat(previousChunks, " is not allowed with stream SSR mode, it will auto changed to \"async\""));
|
|
35
|
+
+ }
|
|
36
|
+
}
|
|
37
|
+
if (isDev() && 'auto' === chain.output.get('publicPath')) {
|
|
38
|
+
var _modernjsConfig_server;
|
|
39
|
+
diff --git a/dist/esm-node/cli/configPlugin.mjs b/dist/esm-node/cli/configPlugin.mjs
|
|
40
|
+
index 722f1bb..dcac7ec 100644
|
|
41
|
+
--- a/dist/esm-node/cli/configPlugin.mjs
|
|
42
|
+
+++ b/dist/esm-node/cli/configPlugin.mjs
|
|
43
|
+
@@ -165,9 +165,12 @@ function patchBundlerConfig(options) {
|
|
44
|
+
if (!chain.output.get('uniqueName')) chain.output.uniqueName(mfConfig.name);
|
|
45
|
+
const splitChunkConfig = chain.optimization.splitChunks.entries();
|
|
46
|
+
if (!isServer) autoDeleteSplitChunkCacheGroups(mfConfig, splitChunkConfig);
|
|
47
|
+
- if (!isServer && enableSSR && splitChunkConfig && 'object' == typeof splitChunkConfig && splitChunkConfig.cacheGroups) {
|
|
48
|
+
+ if (!isServer && enableSSR && splitChunkConfig && 'object' == typeof splitChunkConfig && splitChunkConfig.cacheGroups && splitChunkConfig.chunks !== undefined && splitChunkConfig.chunks !== 'async') {
|
|
49
|
+
+ const previousChunks = splitChunkConfig.chunks;
|
|
50
|
+
splitChunkConfig.chunks = 'async';
|
|
51
|
+
- logger.warn('splitChunks.chunks = async is not allowed with stream SSR mode, it will auto changed to "async"');
|
|
52
|
+
+ if (void 0 !== previousChunks) {
|
|
53
|
+
+ logger.warn(`splitChunks.chunks = ${previousChunks} is not allowed with stream SSR mode, it will auto changed to "async"`);
|
|
54
|
+
+ }
|
|
55
|
+
}
|
|
56
|
+
if (isDev() && 'auto' === chain.output.get('publicPath')) {
|
|
57
|
+
var _modernjsConfig_server;
|