@bleedingdev/modern-js-create 3.4.0-ultramodern.8 → 3.5.0-ultramodern.0

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.
Files changed (135) hide show
  1. package/README.md +25 -23
  2. package/dist/cjs/index.cjs +37 -4
  3. package/dist/cjs/locale/en.cjs +12 -2
  4. package/dist/cjs/locale/zh.cjs +12 -2
  5. package/dist/cjs/ultramodern-tooling/commands.cjs +185 -0
  6. package/dist/cjs/ultramodern-tooling/config.cjs +172 -0
  7. package/dist/cjs/ultramodern-workspace/add-vertical.cjs +87 -75
  8. package/dist/cjs/ultramodern-workspace/{effect-api.cjs → api.cjs} +207 -208
  9. package/dist/cjs/ultramodern-workspace/bridge-config.cjs +327 -0
  10. package/dist/cjs/ultramodern-workspace/codesmith.cjs +1 -0
  11. package/dist/cjs/ultramodern-workspace/contracts.cjs +127 -657
  12. package/dist/cjs/ultramodern-workspace/demo-components.cjs +12 -12
  13. package/dist/cjs/ultramodern-workspace/descriptors.cjs +25 -25
  14. package/dist/cjs/ultramodern-workspace/fs-io.cjs +117 -0
  15. package/dist/cjs/ultramodern-workspace/generation-result.cjs +5 -5
  16. package/dist/cjs/ultramodern-workspace/index.cjs +4 -0
  17. package/dist/cjs/ultramodern-workspace/mf-validation.cjs +571 -0
  18. package/dist/cjs/ultramodern-workspace/module-federation.cjs +33 -18
  19. package/dist/cjs/ultramodern-workspace/overlays.cjs +2 -2
  20. package/dist/cjs/ultramodern-workspace/package-json.cjs +57 -41
  21. package/dist/cjs/ultramodern-workspace/policy.cjs +4 -4
  22. package/dist/cjs/ultramodern-workspace/public-api.cjs +4 -0
  23. package/dist/cjs/ultramodern-workspace/public-surface.cjs +2 -2
  24. package/dist/cjs/ultramodern-workspace/versions.cjs +5 -0
  25. package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +119 -50
  26. package/dist/cjs/ultramodern-workspace/write-workspace.cjs +62 -21
  27. package/dist/esm/index.js +37 -4
  28. package/dist/esm/locale/en.js +12 -2
  29. package/dist/esm/locale/zh.js +12 -2
  30. package/dist/esm/ultramodern-tooling/commands.js +132 -0
  31. package/dist/esm/ultramodern-tooling/config.js +120 -0
  32. package/dist/esm/ultramodern-workspace/add-vertical.js +88 -79
  33. package/dist/esm/ultramodern-workspace/{effect-api.js → api.js} +146 -147
  34. package/dist/esm/ultramodern-workspace/bridge-config.js +270 -0
  35. package/dist/esm/ultramodern-workspace/codesmith.js +1 -0
  36. package/dist/esm/ultramodern-workspace/contracts.js +129 -611
  37. package/dist/esm/ultramodern-workspace/demo-components.js +13 -13
  38. package/dist/esm/ultramodern-workspace/descriptors.js +11 -11
  39. package/dist/esm/ultramodern-workspace/fs-io.js +116 -2
  40. package/dist/esm/ultramodern-workspace/generation-result.js +6 -6
  41. package/dist/esm/ultramodern-workspace/index.js +1 -0
  42. package/dist/esm/ultramodern-workspace/mf-validation.js +516 -0
  43. package/dist/esm/ultramodern-workspace/module-federation.js +34 -19
  44. package/dist/esm/ultramodern-workspace/overlays.js +2 -2
  45. package/dist/esm/ultramodern-workspace/package-json.js +56 -40
  46. package/dist/esm/ultramodern-workspace/policy.js +5 -5
  47. package/dist/esm/ultramodern-workspace/public-api.js +1 -0
  48. package/dist/esm/ultramodern-workspace/public-surface.js +2 -2
  49. package/dist/esm/ultramodern-workspace/versions.js +3 -1
  50. package/dist/esm/ultramodern-workspace/workspace-scripts.js +107 -34
  51. package/dist/esm/ultramodern-workspace/write-workspace.js +64 -26
  52. package/dist/esm-node/index.js +37 -4
  53. package/dist/esm-node/locale/en.js +12 -2
  54. package/dist/esm-node/locale/zh.js +12 -2
  55. package/dist/esm-node/ultramodern-tooling/commands.js +133 -0
  56. package/dist/esm-node/ultramodern-tooling/config.js +121 -0
  57. package/dist/esm-node/ultramodern-workspace/add-vertical.js +88 -79
  58. package/dist/esm-node/ultramodern-workspace/{effect-api.js → api.js} +146 -147
  59. package/dist/esm-node/ultramodern-workspace/bridge-config.js +271 -0
  60. package/dist/esm-node/ultramodern-workspace/codesmith.js +1 -0
  61. package/dist/esm-node/ultramodern-workspace/contracts.js +129 -611
  62. package/dist/esm-node/ultramodern-workspace/demo-components.js +13 -13
  63. package/dist/esm-node/ultramodern-workspace/descriptors.js +11 -11
  64. package/dist/esm-node/ultramodern-workspace/fs-io.js +116 -2
  65. package/dist/esm-node/ultramodern-workspace/generation-result.js +6 -6
  66. package/dist/esm-node/ultramodern-workspace/index.js +1 -0
  67. package/dist/esm-node/ultramodern-workspace/mf-validation.js +517 -0
  68. package/dist/esm-node/ultramodern-workspace/module-federation.js +34 -19
  69. package/dist/esm-node/ultramodern-workspace/overlays.js +2 -2
  70. package/dist/esm-node/ultramodern-workspace/package-json.js +56 -40
  71. package/dist/esm-node/ultramodern-workspace/policy.js +5 -5
  72. package/dist/esm-node/ultramodern-workspace/public-api.js +1 -0
  73. package/dist/esm-node/ultramodern-workspace/public-surface.js +2 -2
  74. package/dist/esm-node/ultramodern-workspace/versions.js +3 -1
  75. package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +107 -34
  76. package/dist/esm-node/ultramodern-workspace/write-workspace.js +64 -26
  77. package/dist/types/locale/en.d.ts +10 -0
  78. package/dist/types/locale/index.d.ts +20 -0
  79. package/dist/types/locale/zh.d.ts +10 -0
  80. package/dist/types/ultramodern-tooling/commands.d.ts +1 -0
  81. package/dist/types/ultramodern-tooling/config.d.ts +43 -0
  82. package/dist/types/ultramodern-workspace/add-vertical.d.ts +5 -2
  83. package/dist/types/ultramodern-workspace/api.d.ts +73 -0
  84. package/dist/types/ultramodern-workspace/bridge-config.d.ts +64 -0
  85. package/dist/types/ultramodern-workspace/codesmith.d.ts +1 -0
  86. package/dist/types/ultramodern-workspace/contracts.d.ts +2 -17
  87. package/dist/types/ultramodern-workspace/descriptors.d.ts +10 -10
  88. package/dist/types/ultramodern-workspace/fs-io.d.ts +1 -0
  89. package/dist/types/ultramodern-workspace/index.d.ts +2 -0
  90. package/dist/types/ultramodern-workspace/mf-validation.d.ts +27 -0
  91. package/dist/types/ultramodern-workspace/package-json.d.ts +5 -4
  92. package/dist/types/ultramodern-workspace/public-api.d.ts +2 -0
  93. package/dist/types/ultramodern-workspace/types.d.ts +9 -7
  94. package/dist/types/ultramodern-workspace/versions.d.ts +2 -0
  95. package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +2 -7
  96. package/dist/types/ultramodern-workspace/write-workspace.d.ts +4 -2
  97. package/package.json +5 -3
  98. package/template-workspace/{.agents → .codex}/skills-lock.json +12 -12
  99. package/template-workspace/.github/workflows/ultramodern-workspace-gates.yml.handlebars +2 -0
  100. package/template-workspace/.gitignore.handlebars +3 -0
  101. package/template-workspace/AGENTS.md.handlebars +11 -5
  102. package/template-workspace/README.md.handlebars +15 -12
  103. package/template-workspace/oxfmt.config.ts +1 -0
  104. package/template-workspace/oxlint.config.ts +1 -0
  105. package/template-workspace/patches/@tanstack__router-core@1.171.13.patch +51 -0
  106. package/template-workspace/pnpm-workspace.yaml.handlebars +4 -0
  107. package/template-workspace/scripts/bootstrap-agent-skills.mjs +77 -67
  108. package/templates/workspace-scripts/assert-mf-types.mjs.handlebars +51 -8
  109. package/templates/workspace-scripts/check-ultramodern-api-boundaries.mts +344 -0
  110. package/templates/workspace-scripts/{check-ultramodern-i18n-boundaries.mjs → check-ultramodern-i18n-boundaries.mts} +1 -1
  111. package/templates/workspace-scripts/generate-public-surface-assets.mjs +246 -9
  112. package/templates/workspace-scripts/proof-cloudflare-version.mjs +277 -9
  113. package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +35 -10
  114. package/templates/workspace-scripts/ultramodern-performance-readiness.mjs +165 -2
  115. package/templates/workspace-scripts/ultramodern-typecheck.mjs +4 -2
  116. package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +840 -84
  117. package/dist/types/ultramodern-workspace/effect-api.d.ts +0 -73
  118. /package/template-workspace/{.agents → .codex}/rstackjs-agent-skills-LICENSE +0 -0
  119. /package/template-workspace/{.agents → .codex}/skills/rsbuild-best-practices/SKILL.md +0 -0
  120. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/SKILL.md +0 -0
  121. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/command-map.md +0 -0
  122. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/common-analysis-patterns.md +0 -0
  123. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-common.md +0 -0
  124. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-rspack.md +0 -0
  125. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-webpack.md +0 -0
  126. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor.md +0 -0
  127. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/rsdoctor-data-types.md +0 -0
  128. /package/template-workspace/{.agents → .codex}/skills/rslib-best-practices/SKILL.md +0 -0
  129. /package/template-workspace/{.agents → .codex}/skills/rslib-modern-package/SKILL.md +0 -0
  130. /package/template-workspace/{.agents → .codex}/skills/rspack-best-practices/SKILL.md +0 -0
  131. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/SKILL.md +0 -0
  132. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/bottlenecks.md +0 -0
  133. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/tracing-guide.md +0 -0
  134. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/scripts/analyze_trace.js +0 -0
  135. /package/template-workspace/{.agents → .codex}/skills/rstest-best-practices/SKILL.md +0 -0
@@ -0,0 +1,571 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
12
+ (()=>{
13
+ __webpack_require__.d = (exports1, getters, values)=>{
14
+ var define = (defs, kind)=>{
15
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
16
+ enumerable: true,
17
+ [kind]: defs[key]
18
+ });
19
+ };
20
+ define(getters, "get");
21
+ define(values, "value");
22
+ };
23
+ })();
24
+ (()=>{
25
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
26
+ })();
27
+ (()=>{
28
+ __webpack_require__.r = (exports1)=>{
29
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
30
+ value: 'Module'
31
+ });
32
+ Object.defineProperty(exports1, '__esModule', {
33
+ value: true
34
+ });
35
+ };
36
+ })();
37
+ var __webpack_exports__ = {};
38
+ __webpack_require__.r(__webpack_exports__);
39
+ __webpack_require__.d(__webpack_exports__, {
40
+ discoverModuleFederationConfigs: ()=>discoverModuleFederationConfigs,
41
+ inspectModuleFederationConfigSource: ()=>inspectModuleFederationConfigSource,
42
+ validateModuleFederationTypes: ()=>validateModuleFederationTypes
43
+ });
44
+ const external_node_fs_namespaceObject = require("node:fs");
45
+ var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
46
+ const external_node_path_namespaceObject = require("node:path");
47
+ var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
48
+ const moduleFederationConfigFile = 'module-federation.config.ts';
49
+ const mfTypesArchive = 'dist/@mf-types.zip';
50
+ const generatedMetadataPaths = [
51
+ '.modernjs/ultramodern.json'
52
+ ];
53
+ const defaultAppRootDirs = [
54
+ 'apps',
55
+ 'verticals'
56
+ ];
57
+ const skippedScanDirs = new Set([
58
+ '.git',
59
+ '.modernjs',
60
+ '.nx',
61
+ '.turbo',
62
+ 'coverage',
63
+ 'dist',
64
+ 'node_modules'
65
+ ]);
66
+ function isRecord(value) {
67
+ return null !== value && 'object' == typeof value && !Array.isArray(value);
68
+ }
69
+ function toPosixPath(value) {
70
+ return value.split(external_node_path_default().sep).join('/');
71
+ }
72
+ function normalizeRelativePath(value) {
73
+ const normalized = value.replace(/\\/g, '/').replace(/^\.\/+/u, '');
74
+ const trimmed = normalized.replace(/\/+$/u, '');
75
+ return '' === trimmed ? '.' : trimmed;
76
+ }
77
+ function relativePath(root, target) {
78
+ return normalizeRelativePath(toPosixPath(external_node_path_default().relative(root, target)));
79
+ }
80
+ function readJsonIfExists(filePath) {
81
+ if (!external_node_fs_default().existsSync(filePath)) return;
82
+ return JSON.parse(external_node_fs_default().readFileSync(filePath, 'utf-8'));
83
+ }
84
+ function addMetadataAppDir(value, appDirs, hint = '') {
85
+ if (!isRecord(value)) return;
86
+ const pathValue = 'string' == typeof value.path ? value.path : 'string' == typeof value.directory ? value.directory : void 0;
87
+ const hasModuleFederationDeclaration = isRecord(value.moduleFederation) || 'string' == typeof value.moduleFederationName || 'apps' === hint || 'verticals' === hint || 'remotes' === hint || 'moduleFederation' === hint;
88
+ if (pathValue && hasModuleFederationDeclaration && !external_node_path_default().isAbsolute(pathValue)) appDirs.add(normalizeRelativePath(pathValue));
89
+ }
90
+ function collectMetadataAppDirs(value, appDirs, hint = '') {
91
+ if (Array.isArray(value)) {
92
+ for (const entry of value)collectMetadataAppDirs(entry, appDirs, hint);
93
+ return;
94
+ }
95
+ if (!isRecord(value)) return;
96
+ addMetadataAppDir(value, appDirs, hint);
97
+ for (const [key, entry] of Object.entries(value))collectMetadataAppDirs(entry, appDirs, key);
98
+ }
99
+ function literalRootFromPattern(pattern) {
100
+ const normalized = normalizeRelativePath(pattern);
101
+ if ('.' === normalized || external_node_path_default().isAbsolute(normalized) || normalized.startsWith('../')) return;
102
+ const segments = normalized.split('/');
103
+ const literalSegments = [];
104
+ for (const segment of segments){
105
+ if (/[*?[\]{}]/u.test(segment)) break;
106
+ literalSegments.push(segment);
107
+ }
108
+ return literalSegments.length > 0 ? literalSegments.join('/') : void 0;
109
+ }
110
+ function collectBridgeScanRoots(value, roots) {
111
+ if (Array.isArray(value)) {
112
+ for (const entry of value)collectBridgeScanRoots(entry, roots);
113
+ return;
114
+ }
115
+ if (!isRecord(value)) return;
116
+ const workspacePackages = value.bridge;
117
+ if (isRecord(workspacePackages)) {
118
+ const entries = workspacePackages.workspacePackages;
119
+ if (Array.isArray(entries)) {
120
+ for (const entry of entries)if (isRecord(entry) && 'string' == typeof entry.pattern) {
121
+ const root = literalRootFromPattern(entry.pattern);
122
+ if (root) roots.add(root);
123
+ }
124
+ }
125
+ }
126
+ for (const entry of Object.values(value))collectBridgeScanRoots(entry, roots);
127
+ }
128
+ function readGeneratedMetadata(workspaceRoot) {
129
+ return generatedMetadataPaths.map((metadataPath)=>readJsonIfExists(external_node_path_default().join(workspaceRoot, metadataPath))).filter((metadata)=>void 0 !== metadata);
130
+ }
131
+ function firstSegment(appDir) {
132
+ if ('.' === appDir) return;
133
+ return appDir.split('/')[0];
134
+ }
135
+ function scanForModuleFederationConfigs(workspaceRoot, scanRoot, appDirs) {
136
+ const absoluteRoot = external_node_path_default().join(workspaceRoot, scanRoot);
137
+ if (!external_node_fs_default().existsSync(absoluteRoot) || !external_node_fs_default().statSync(absoluteRoot).isDirectory()) return;
138
+ const visit = (directory)=>{
139
+ for (const entry of external_node_fs_default().readdirSync(directory, {
140
+ withFileTypes: true
141
+ })){
142
+ if (entry.isDirectory()) {
143
+ if (!skippedScanDirs.has(entry.name)) visit(external_node_path_default().join(directory, entry.name));
144
+ continue;
145
+ }
146
+ if (entry.isFile() && entry.name === moduleFederationConfigFile) appDirs.add(relativePath(workspaceRoot, directory));
147
+ }
148
+ };
149
+ visit(absoluteRoot);
150
+ }
151
+ function discoverModuleFederationConfigs(options) {
152
+ const workspaceRoot = external_node_path_default().resolve(options.workspaceRoot);
153
+ const appDirs = new Set();
154
+ if (options.appDirs && options.appDirs.length > 0) for (const appDir of options.appDirs)appDirs.add(normalizeRelativePath(appDir));
155
+ else {
156
+ const metadata = readGeneratedMetadata(workspaceRoot);
157
+ const scanRoots = new Set(defaultAppRootDirs);
158
+ for (const metadataEntry of metadata){
159
+ collectMetadataAppDirs(metadataEntry, appDirs);
160
+ collectBridgeScanRoots(metadataEntry, scanRoots);
161
+ }
162
+ for (const appDir of appDirs){
163
+ const segment = firstSegment(appDir);
164
+ if (segment) scanRoots.add(segment);
165
+ }
166
+ if (external_node_fs_default().existsSync(external_node_path_default().join(workspaceRoot, moduleFederationConfigFile))) appDirs.add('.');
167
+ for (const scanRoot of scanRoots)scanForModuleFederationConfigs(workspaceRoot, scanRoot, appDirs);
168
+ }
169
+ return Array.from(appDirs).sort().map((appDir)=>({
170
+ appDir,
171
+ configPath: external_node_path_default().join(workspaceRoot, appDir, moduleFederationConfigFile)
172
+ }));
173
+ }
174
+ function isEscaped(source, index) {
175
+ let slashCount = 0;
176
+ for(let cursor = index - 1; cursor >= 0 && '\\' === source[cursor]; cursor -= 1)slashCount += 1;
177
+ return slashCount % 2 === 1;
178
+ }
179
+ function skipQuoted(source, start, quote) {
180
+ for(let index = start + 1; index < source.length; index += 1)if (source[index] === quote && !isEscaped(source, index)) return index + 1;
181
+ return source.length;
182
+ }
183
+ function skipLineComment(source, start) {
184
+ const newline = source.indexOf('\n', start + 2);
185
+ return -1 === newline ? source.length : newline + 1;
186
+ }
187
+ function skipBlockComment(source, start) {
188
+ const close = source.indexOf('*/', start + 2);
189
+ return -1 === close ? source.length : close + 2;
190
+ }
191
+ function skipTemplateExpression(source, start) {
192
+ let depth = 1;
193
+ for(let index = start + 1; index < source.length; index += 1){
194
+ const char = source[index];
195
+ const next = source[index + 1];
196
+ if ("'" === char) {
197
+ index = skipQuoted(source, index, "'") - 1;
198
+ continue;
199
+ }
200
+ if ('"' === char) {
201
+ index = skipQuoted(source, index, '"') - 1;
202
+ continue;
203
+ }
204
+ if ('`' === char) {
205
+ index = skipTemplate(source, index) - 1;
206
+ continue;
207
+ }
208
+ if ('/' === char && '/' === next) {
209
+ index = skipLineComment(source, index) - 1;
210
+ continue;
211
+ }
212
+ if ('/' === char && '*' === next) {
213
+ index = skipBlockComment(source, index) - 1;
214
+ continue;
215
+ }
216
+ if ('{' === char) {
217
+ depth += 1;
218
+ continue;
219
+ }
220
+ if ('}' === char) {
221
+ depth -= 1;
222
+ if (0 === depth) return index + 1;
223
+ }
224
+ }
225
+ return source.length;
226
+ }
227
+ function skipTemplate(source, start) {
228
+ for(let index = start + 1; index < source.length; index += 1){
229
+ const char = source[index];
230
+ const next = source[index + 1];
231
+ if ('`' === char && !isEscaped(source, index)) return index + 1;
232
+ if ('$' === char && '{' === next && !isEscaped(source, index)) index = skipTemplateExpression(source, index + 1) - 1;
233
+ }
234
+ return source.length;
235
+ }
236
+ function skipSyntax(source, index) {
237
+ const char = source[index];
238
+ const next = source[index + 1];
239
+ if ("'" === char) return skipQuoted(source, index, "'");
240
+ if ('"' === char) return skipQuoted(source, index, '"');
241
+ if ('`' === char) return skipTemplate(source, index);
242
+ if ('/' === char && '/' === next) return skipLineComment(source, index);
243
+ if ('/' === char && '*' === next) return skipBlockComment(source, index);
244
+ return index;
245
+ }
246
+ function findBalanced(source, start, open, close) {
247
+ let depth = 1;
248
+ for(let index = start + 1; index < source.length; index += 1){
249
+ const skipped = skipSyntax(source, index);
250
+ if (skipped !== index) {
251
+ index = skipped - 1;
252
+ continue;
253
+ }
254
+ if (source[index] === open) {
255
+ depth += 1;
256
+ continue;
257
+ }
258
+ if (source[index] === close) {
259
+ depth -= 1;
260
+ if (0 === depth) return index;
261
+ }
262
+ }
263
+ }
264
+ function skipWhitespaceAndComments(source, start) {
265
+ let index = start;
266
+ while(index < source.length){
267
+ const char = source[index];
268
+ const next = source[index + 1];
269
+ if (/\s/u.test(char ?? '')) {
270
+ index += 1;
271
+ continue;
272
+ }
273
+ if ('/' === char && '/' === next) {
274
+ index = skipLineComment(source, index);
275
+ continue;
276
+ }
277
+ if ('/' === char && '*' === next) {
278
+ index = skipBlockComment(source, index);
279
+ continue;
280
+ }
281
+ break;
282
+ }
283
+ return index;
284
+ }
285
+ function hasIdentifierBoundary(source, start, end) {
286
+ return !/[$\w]/u.test(source[start - 1] ?? '') && !/[$\w]/u.test(source[end] ?? '');
287
+ }
288
+ function findCreateModuleFederationConfigObject(source) {
289
+ const callee = 'createModuleFederationConfig';
290
+ let offset = 0;
291
+ while(offset < source.length){
292
+ const index = source.indexOf(callee, offset);
293
+ if (-1 === index) break;
294
+ offset = index + callee.length;
295
+ if (!hasIdentifierBoundary(source, index, offset)) continue;
296
+ const parenIndex = skipWhitespaceAndComments(source, offset);
297
+ if ('(' !== source[parenIndex]) continue;
298
+ const argumentIndex = skipWhitespaceAndComments(source, parenIndex + 1);
299
+ if ('{' !== source[argumentIndex]) throw new Error('Module Federation config must pass a static object literal to createModuleFederationConfig.');
300
+ const closeIndex = findBalanced(source, argumentIndex, '{', '}');
301
+ if (void 0 === closeIndex) throw new Error('Module Federation config object literal is not closed.');
302
+ return source.slice(argumentIndex, closeIndex + 1);
303
+ }
304
+ }
305
+ function findExportDefaultObject(source) {
306
+ const exportDefault = 'export default';
307
+ const index = source.indexOf(exportDefault);
308
+ if (-1 === index) return;
309
+ const objectStart = skipWhitespaceAndComments(source, index + exportDefault.length);
310
+ if ('{' !== source[objectStart]) return;
311
+ const objectEnd = findBalanced(source, objectStart, '{', '}');
312
+ if (void 0 === objectEnd) throw new Error('Module Federation export default object is not closed.');
313
+ return source.slice(objectStart, objectEnd + 1);
314
+ }
315
+ function getOuterBlock(source, open, close) {
316
+ const trimmed = source.trim();
317
+ if (trimmed[0] !== open) return;
318
+ const end = findBalanced(trimmed, 0, open, close);
319
+ if (void 0 === end) return;
320
+ const suffix = trimmed.slice(end + 1).trim();
321
+ if ('' !== suffix && !suffix.startsWith('as ') && !suffix.startsWith('satisfies ')) return;
322
+ return {
323
+ inner: trimmed.slice(1, end),
324
+ suffix
325
+ };
326
+ }
327
+ function splitTopLevelEntries(source) {
328
+ const entries = [];
329
+ let start = 0;
330
+ let braceDepth = 0;
331
+ let bracketDepth = 0;
332
+ let parenDepth = 0;
333
+ for(let index = 0; index < source.length; index += 1){
334
+ const skipped = skipSyntax(source, index);
335
+ if (skipped !== index) {
336
+ index = skipped - 1;
337
+ continue;
338
+ }
339
+ const char = source[index];
340
+ if ('{' === char) braceDepth += 1;
341
+ else if ('}' === char) braceDepth -= 1;
342
+ else if ('[' === char) bracketDepth += 1;
343
+ else if (']' === char) bracketDepth -= 1;
344
+ else if ('(' === char) parenDepth += 1;
345
+ else if (')' === char) parenDepth -= 1;
346
+ else if (',' === char && 0 === braceDepth && 0 === bracketDepth && 0 === parenDepth) {
347
+ const entry = source.slice(start, index).trim();
348
+ if (entry) entries.push(entry);
349
+ start = index + 1;
350
+ }
351
+ }
352
+ const finalEntry = source.slice(start).trim();
353
+ if (finalEntry) entries.push(finalEntry);
354
+ return entries;
355
+ }
356
+ function findTopLevelColon(source) {
357
+ let braceDepth = 0;
358
+ let bracketDepth = 0;
359
+ let parenDepth = 0;
360
+ for(let index = 0; index < source.length; index += 1){
361
+ const skipped = skipSyntax(source, index);
362
+ if (skipped !== index) {
363
+ index = skipped - 1;
364
+ continue;
365
+ }
366
+ const char = source[index];
367
+ if ('{' === char) braceDepth += 1;
368
+ else if ('}' === char) braceDepth -= 1;
369
+ else if ('[' === char) bracketDepth += 1;
370
+ else if (']' === char) bracketDepth -= 1;
371
+ else if ('(' === char) parenDepth += 1;
372
+ else if (')' === char) parenDepth -= 1;
373
+ else if (':' === char && 0 === braceDepth && 0 === bracketDepth && 0 === parenDepth) return index;
374
+ }
375
+ return -1;
376
+ }
377
+ function stripConstAssertion(source) {
378
+ return source.trim().replace(/\s+as\s+const\s*$/u, '').trim();
379
+ }
380
+ function unescapeSingleQuotedString(value) {
381
+ return value.replace(/\\(['"\\nrtbfv0])/gu, (_, sequence)=>{
382
+ switch(sequence){
383
+ case 'n':
384
+ return '\n';
385
+ case 'r':
386
+ return '\r';
387
+ case 't':
388
+ return '\t';
389
+ case 'b':
390
+ return '\b';
391
+ case 'f':
392
+ return '\f';
393
+ case 'v':
394
+ return '\v';
395
+ case '0':
396
+ return '\0';
397
+ default:
398
+ return sequence;
399
+ }
400
+ });
401
+ }
402
+ function parseLiteralString(source) {
403
+ if (void 0 === source) return;
404
+ const trimmed = stripConstAssertion(source);
405
+ const quote = trimmed[0];
406
+ if ("'" !== quote && '"' !== quote && '`' !== quote) return;
407
+ if ('`' === quote) {
408
+ if (trimmed.includes('${')) return;
409
+ const close = trimmed.lastIndexOf('`');
410
+ return close > 0 ? trimmed.slice(1, close).replaceAll('\\`', '`') : void 0;
411
+ }
412
+ const close = trimmed.lastIndexOf(quote);
413
+ if (close <= 0 || '' !== trimmed.slice(close + 1).trim()) return;
414
+ const content = trimmed.slice(1, close);
415
+ if ('"' === quote) try {
416
+ return JSON.parse(trimmed);
417
+ } catch {
418
+ return;
419
+ }
420
+ return unescapeSingleQuotedString(content);
421
+ }
422
+ function parseObjectKey(source) {
423
+ const trimmed = source.trim();
424
+ const literal = parseLiteralString(trimmed);
425
+ if (void 0 !== literal) return literal;
426
+ return /^[$A-Z_a-z][$\w]*$/u.test(trimmed) ? trimmed : void 0;
427
+ }
428
+ function parseObjectLiteral(source) {
429
+ if (void 0 === source) return;
430
+ const block = getOuterBlock(source, '{', '}');
431
+ if (!block) return;
432
+ const properties = new Map();
433
+ let hasSpread = false;
434
+ for (const entry of splitTopLevelEntries(block.inner)){
435
+ if (entry.startsWith('...')) {
436
+ hasSpread = true;
437
+ continue;
438
+ }
439
+ const colon = findTopLevelColon(entry);
440
+ if (-1 === colon) {
441
+ hasSpread = true;
442
+ continue;
443
+ }
444
+ const key = parseObjectKey(entry.slice(0, colon));
445
+ if (void 0 === key) {
446
+ hasSpread = true;
447
+ continue;
448
+ }
449
+ properties.set(key, entry.slice(colon + 1).trim());
450
+ }
451
+ return {
452
+ hasSpread,
453
+ properties
454
+ };
455
+ }
456
+ function parseArrayLiteral(source) {
457
+ if (void 0 === source) return;
458
+ const block = getOuterBlock(source, '[', ']');
459
+ if (!block) return;
460
+ const entries = splitTopLevelEntries(block.inner);
461
+ const exposes = [];
462
+ for (const entry of entries){
463
+ const expose = parseLiteralString(entry);
464
+ if (void 0 === expose) return;
465
+ exposes.push(expose);
466
+ }
467
+ return exposes;
468
+ }
469
+ function extractExposes(configPath, value) {
470
+ if (void 0 === value) return [];
471
+ const object = parseObjectLiteral(value);
472
+ if (object) {
473
+ if (object.hasSpread) throw new Error(`Cannot statically extract Module Federation exposes from ${configPath}; use a literal exposes object without spreads.`);
474
+ return Array.from(object.properties.keys()).sort();
475
+ }
476
+ const array = parseArrayLiteral(value);
477
+ if (array) return array.sort();
478
+ throw new Error(`Cannot statically extract Module Federation exposes from ${configPath}; use a literal exposes object or string array.`);
479
+ }
480
+ function extractDtsSettings(configPath, value) {
481
+ if (void 0 === value) return {};
482
+ const dts = parseObjectLiteral(value);
483
+ if (!dts || dts.hasSpread) throw new Error(`Cannot statically extract Module Federation DTS settings from ${configPath}; use a literal dts object.`);
484
+ const generateTypes = parseObjectLiteral(dts.properties.get('generateTypes'));
485
+ if (generateTypes?.hasSpread) throw new Error(`Cannot statically extract Module Federation generateTypes settings from ${configPath}; use a literal generateTypes object.`);
486
+ return {
487
+ compilerInstance: parseLiteralString(generateTypes?.properties.get('compilerInstance')),
488
+ tsConfigPath: parseLiteralString(dts.properties.get('tsConfigPath'))
489
+ };
490
+ }
491
+ function hasHostOnlyNoExposesDeclaration(source) {
492
+ return /@?ultramodern-mf\s*:?\s*(?:host-only|no-exposes)\b/iu.test(source);
493
+ }
494
+ function inspectModuleFederationConfigSource(source, appDir, configPath) {
495
+ const configObject = findCreateModuleFederationConfigObject(source) ?? findExportDefaultObject(source);
496
+ if (!configObject) throw new Error(`Cannot statically inspect Module Federation config ${configPath}; export or pass a literal config object.`);
497
+ const properties = parseObjectLiteral(configObject);
498
+ if (!properties) throw new Error(`Cannot statically inspect Module Federation config ${configPath}; expected a literal config object.`);
499
+ if (properties.hasSpread) throw new Error(`Cannot statically inspect Module Federation config ${configPath}; top-level config spreads are not supported.`);
500
+ const exposes = extractExposes(configPath, properties.properties.get('exposes'));
501
+ const hostOnlyNoExposes = hasHostOnlyNoExposesDeclaration(source);
502
+ if (hostOnlyNoExposes && exposes.length > 0) throw new Error(`Module Federation host-only/no-exposes declaration conflicts with actual exposes in ${configPath}.`);
503
+ return {
504
+ appDir,
505
+ configPath,
506
+ dts: extractDtsSettings(configPath, properties.properties.get('dts')),
507
+ exposes,
508
+ hostOnlyNoExposes
509
+ };
510
+ }
511
+ function assertExposedAppDtsSettings(app) {
512
+ if ('tsgo' !== app.dts.compilerInstance) throw new Error(`Module Federation DTS compilerInstance must be "tsgo" for ${app.appDir}.`);
513
+ if ('./tsconfig.mf-types.json' !== app.dts.tsConfigPath) throw new Error(`Module Federation DTS tsConfigPath must be "./tsconfig.mf-types.json" for ${app.appDir}.`);
514
+ }
515
+ function assertTypesArchive(workspaceRoot, appDir) {
516
+ const typesArchivePath = external_node_path_default().join(workspaceRoot, appDir, mfTypesArchive);
517
+ if (!external_node_fs_default().existsSync(typesArchivePath)) throw new Error(`Missing Module Federation DTS archive: ${relativePath(workspaceRoot, typesArchivePath)}`);
518
+ if (0 === external_node_fs_default().statSync(typesArchivePath).size) throw new Error(`Empty Module Federation DTS archive: ${relativePath(workspaceRoot, typesArchivePath)}`);
519
+ }
520
+ function validateModuleFederationTypes(options) {
521
+ const workspaceRoot = external_node_path_default().resolve(options.workspaceRoot);
522
+ const discoveredConfigs = discoverModuleFederationConfigs({
523
+ ...options,
524
+ workspaceRoot
525
+ });
526
+ const apps = [];
527
+ const missingConfigPaths = [];
528
+ for (const discoveredConfig of discoveredConfigs){
529
+ if (!external_node_fs_default().existsSync(discoveredConfig.configPath)) {
530
+ missingConfigPaths.push(relativePath(workspaceRoot, discoveredConfig.configPath));
531
+ continue;
532
+ }
533
+ const configPath = relativePath(workspaceRoot, discoveredConfig.configPath);
534
+ apps.push(inspectModuleFederationConfigSource(external_node_fs_default().readFileSync(discoveredConfig.configPath, 'utf-8'), discoveredConfig.appDir, configPath));
535
+ }
536
+ if (missingConfigPaths.length > 0) throw new Error(`Missing Module Federation config: ${missingConfigPaths.join(', ')}`);
537
+ const noExposeApps = apps.filter((app)=>0 === app.exposes.length && !app.hostOnlyNoExposes);
538
+ if (noExposeApps.length > 0) {
539
+ const suffix = 0 === apps.filter((app)=>app.exposes.length > 0).length ? ' Validation would otherwise validate zero exposed apps.' : '';
540
+ throw new Error(`Module Federation configs declare no exposes without an explicit host-only/no-exposes declaration: ${noExposeApps.map((app)=>app.appDir).join(', ')}.${suffix}`);
541
+ }
542
+ let exposedAppCount = 0;
543
+ let hostOnlyAppCount = 0;
544
+ for (const app of apps){
545
+ if (app.hostOnlyNoExposes) {
546
+ hostOnlyAppCount += 1;
547
+ continue;
548
+ }
549
+ assertExposedAppDtsSettings(app);
550
+ assertTypesArchive(workspaceRoot, app.appDir);
551
+ exposedAppCount += 1;
552
+ }
553
+ if (apps.length > 0 && 0 === exposedAppCount && hostOnlyAppCount !== apps.length) throw new Error('Module Federation validation inspected configs but validated zero exposed apps. Declare host-only/no-exposes intent only for host apps without exposes.');
554
+ return {
555
+ apps,
556
+ configCount: apps.length,
557
+ exposedAppCount,
558
+ hostOnlyAppCount
559
+ };
560
+ }
561
+ exports.discoverModuleFederationConfigs = __webpack_exports__.discoverModuleFederationConfigs;
562
+ exports.inspectModuleFederationConfigSource = __webpack_exports__.inspectModuleFederationConfigSource;
563
+ exports.validateModuleFederationTypes = __webpack_exports__.validateModuleFederationTypes;
564
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
565
+ "discoverModuleFederationConfigs",
566
+ "inspectModuleFederationConfigSource",
567
+ "validateModuleFederationTypes"
568
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
569
+ Object.defineProperty(exports, '__esModule', {
570
+ value: true
571
+ });
@@ -56,19 +56,26 @@ const external_policy_cjs_namespaceObject = require("./policy.cjs");
56
56
  const external_types_cjs_namespaceObject = require("./types.cjs");
57
57
  const external_versions_cjs_namespaceObject = require("./versions.cjs");
58
58
  function createAppModernConfig(scope, app) {
59
- const bffImport = (0, external_descriptors_cjs_namespaceObject.appHasEffectApi)(app) ? "import { bffPlugin } from '@modern-js/plugin-bff';\n" : '';
60
- const bffConfig = (0, external_descriptors_cjs_namespaceObject.appHasEffectApi)(app) ? ` bff: {
59
+ const bffImport = (0, external_descriptors_cjs_namespaceObject.appHasApi)(app) ? "import { bffPlugin } from '@modern-js/plugin-bff';\n" : '';
60
+ const bffConfig = (0, external_descriptors_cjs_namespaceObject.appHasApi)(app) ? ` bff: {
61
61
  effect: {
62
- entry: './api/effect/index',
62
+ entry: './api/index',
63
63
  openapi: {
64
64
  path: '/openapi.json',
65
65
  },
66
+ strictEffectApproach: true,
66
67
  },
67
- prefix: '${(0, external_descriptors_cjs_namespaceObject.effectApiPrefix)(app)}',
68
+ prefix: '${(0, external_descriptors_cjs_namespaceObject.resolveApiPrefix)(app)}',
68
69
  runtimeFramework: 'effect',
69
70
  },
70
71
  ` : '';
71
- const bffPluginEntry = (0, external_descriptors_cjs_namespaceObject.appHasEffectApi)(app) ? ' bffPlugin(),\n' : '';
72
+ const bffPluginEntry = (0, external_descriptors_cjs_namespaceObject.appHasApi)(app) ? ' bffPlugin(),\n' : '';
73
+ const defaultAssetPrefixSource = 'shell' === app.kind ? "const defaultAssetPrefix = '/';" : `const remoteAssetOrigin =
74
+ configuredCloudflareUrl ||
75
+ inferredCloudflareUrl ||
76
+ (cloudflareDeployEnabled ? '/' : \`http://localhost:\${port}\`);
77
+ const defaultRemoteAssetPrefix = \`\${remoteAssetOrigin.replace(/\\/+$/u, '')}/\`;
78
+ const defaultAssetPrefix = defaultRemoteAssetPrefix;`;
72
79
  return `// @effect-diagnostics processEnv:off
73
80
  import {
74
81
  appTools,
@@ -115,6 +122,8 @@ const configuredSiteUrl = envValue('MODERN_PUBLIC_SITE_URL');
115
122
  const configuredCloudflareUrl = envValue('${(0, external_descriptors_cjs_namespaceObject.createCloudflarePublicUrlEnv)(app)}');
116
123
  const configuredUltramodernAssetPrefix = envValue('ULTRAMODERN_ASSET_PREFIX');
117
124
  const configuredModernAssetPrefix = envValue('MODERN_ASSET_PREFIX');
125
+ const moduleFederationDevServerOrigin =
126
+ envValue('ULTRAMODERN_MF_DEV_ORIGIN') || 'http://localhost:${external_descriptors_cjs_namespaceObject.shellApp.port}';
118
127
  const cloudflareWorkersDevSubdomain = envValue(
119
128
  'ULTRAMODERN_CLOUDFLARE_WORKERS_DEV_SUBDOMAIN',
120
129
  );
@@ -129,12 +138,12 @@ const siteUrl =
129
138
  configuredCloudflareUrl ||
130
139
  inferredCloudflareUrl ||
131
140
  \`http://localhost:\${port}\`;
132
- // Asset loading is intentionally independent from the canonical site URL and
133
- // deployment public URL. Without an explicit asset prefix, assets stay
134
- // origin-relative so self-hosted apps, tunnels, and reverse proxies never leak
135
- // localhost URLs into production HTML.
141
+ ${defaultAssetPrefixSource}
142
+ // Asset loading is intentionally independent from the canonical site URL.
143
+ // Module Federation remotes must publish an absolute publicPath so browsers
144
+ // load remoteEntry.js and exposed chunks from the remote origin, not the host.
136
145
  const assetPrefix =
137
- configuredModernAssetPrefix || configuredUltramodernAssetPrefix || '/';
146
+ configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix;
138
147
 
139
148
  if (
140
149
  cloudflareDeployEnabled &&
@@ -200,7 +209,7 @@ ${bffConfig} ...(cloudflareDeployEnabled
200
209
  '/@mf-types',
201
210
  '/assets',
202
211
  '/bundles',
203
- '${(0, external_descriptors_cjs_namespaceObject.effectApiPrefix)(app)}',
212
+ '${(0, external_descriptors_cjs_namespaceObject.resolveApiPrefix)(app)}',
204
213
  '/locales',
205
214
  '/mf-manifest.json',
206
215
  '/mf-stats.json',
@@ -238,6 +247,9 @@ ${bffPluginEntry} moduleFederationPlugin(),
238
247
  },
239
248
  mainEntryName: 'index',
240
249
  },
250
+ splitChunks: {
251
+ chunks: 'async',
252
+ },
241
253
  tools: {
242
254
  autoprefixer: {
243
255
  overrideBrowserslist: ['defaults'],
@@ -246,12 +258,14 @@ ${bffPluginEntry} moduleFederationPlugin(),
246
258
  chain.output
247
259
  .uniqueName('${(0, external_naming_cjs_namespaceObject.createRspackUniqueName)(app)}')
248
260
  .chunkLoadingGlobal('${(0, external_naming_cjs_namespaceObject.createRspackChunkLoadingGlobal)(app)}');
249
- chain.ignoreWarnings([
250
- {
251
- message: /the request of a dependency is an expression/u,
252
- module: /modern-js-plugin-i18n/u,
253
- },
254
- ]);
261
+ },
262
+ devServer: {
263
+ headers: {
264
+ 'Access-Control-Allow-Headers':
265
+ 'Accept, Authorization, Content-Type, X-Requested-With',
266
+ 'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
267
+ 'Access-Control-Allow-Origin': moduleFederationDevServerOrigin,
268
+ },
255
269
  },
256
270
  },
257
271
  },
@@ -376,6 +390,7 @@ function createShellModuleFederationConfig(scope, remotes = []) {
376
390
  verticalRefs: remotes.map((remote)=>remote.id)
377
391
  };
378
392
  return `// @effect-diagnostics nodeBuiltinImport:off processEnv:off
393
+ // ultramodern-mf: host-only
379
394
  import { createRequire } from 'node:module';
380
395
  import { createModuleFederationConfig } from '@module-federation/modern-js-v3';
381
396
  import { dependencies } from './package.json';
@@ -432,7 +447,7 @@ export const ultramodernUiMarker = {
432
447
 
433
448
  export const ultramodernApiMarker = {
434
449
  ...ultramodernVerticalIdentity,
435
- surface: 'effect-bff',
450
+ surface: 'api',
436
451
  } as const;
437
452
  `;
438
453
  }