@bleedingdev/modern-js-create 3.4.0-ultramodern.2 → 3.4.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.
Files changed (128) hide show
  1. package/README.md +13 -11
  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 +79 -61
  8. package/dist/cjs/ultramodern-workspace/bridge-config.cjs +327 -0
  9. package/dist/cjs/ultramodern-workspace/codesmith.cjs +1 -0
  10. package/dist/cjs/ultramodern-workspace/contracts.cjs +121 -648
  11. package/dist/cjs/ultramodern-workspace/demo-components.cjs +26 -33
  12. package/dist/cjs/ultramodern-workspace/descriptors.cjs +4 -4
  13. package/dist/cjs/ultramodern-workspace/effect-api.cjs +230 -100
  14. package/dist/cjs/ultramodern-workspace/fs-io.cjs +117 -0
  15. package/dist/cjs/ultramodern-workspace/generation-result.cjs +1 -1
  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 +51 -20
  19. package/dist/cjs/ultramodern-workspace/package-json.cjs +62 -19
  20. package/dist/cjs/ultramodern-workspace/policy.cjs +2 -2
  21. package/dist/cjs/ultramodern-workspace/public-api.cjs +4 -0
  22. package/dist/cjs/ultramodern-workspace/versions.cjs +5 -0
  23. package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +80 -43
  24. package/dist/cjs/ultramodern-workspace/write-workspace.cjs +63 -20
  25. package/dist/esm/index.js +37 -4
  26. package/dist/esm/locale/en.js +12 -2
  27. package/dist/esm/locale/zh.js +12 -2
  28. package/dist/esm/ultramodern-tooling/commands.js +132 -0
  29. package/dist/esm/ultramodern-tooling/config.js +120 -0
  30. package/dist/esm/ultramodern-workspace/add-vertical.js +81 -66
  31. package/dist/esm/ultramodern-workspace/bridge-config.js +270 -0
  32. package/dist/esm/ultramodern-workspace/codesmith.js +1 -0
  33. package/dist/esm/ultramodern-workspace/contracts.js +124 -603
  34. package/dist/esm/ultramodern-workspace/demo-components.js +26 -33
  35. package/dist/esm/ultramodern-workspace/descriptors.js +2 -2
  36. package/dist/esm/ultramodern-workspace/effect-api.js +230 -100
  37. package/dist/esm/ultramodern-workspace/fs-io.js +116 -2
  38. package/dist/esm/ultramodern-workspace/generation-result.js +2 -2
  39. package/dist/esm/ultramodern-workspace/index.js +1 -0
  40. package/dist/esm/ultramodern-workspace/mf-validation.js +516 -0
  41. package/dist/esm/ultramodern-workspace/module-federation.js +49 -21
  42. package/dist/esm/ultramodern-workspace/package-json.js +60 -20
  43. package/dist/esm/ultramodern-workspace/policy.js +2 -2
  44. package/dist/esm/ultramodern-workspace/public-api.js +1 -0
  45. package/dist/esm/ultramodern-workspace/versions.js +3 -1
  46. package/dist/esm/ultramodern-workspace/workspace-scripts.js +78 -26
  47. package/dist/esm/ultramodern-workspace/write-workspace.js +67 -27
  48. package/dist/esm-node/index.js +37 -4
  49. package/dist/esm-node/locale/en.js +12 -2
  50. package/dist/esm-node/locale/zh.js +12 -2
  51. package/dist/esm-node/ultramodern-tooling/commands.js +133 -0
  52. package/dist/esm-node/ultramodern-tooling/config.js +121 -0
  53. package/dist/esm-node/ultramodern-workspace/add-vertical.js +81 -66
  54. package/dist/esm-node/ultramodern-workspace/bridge-config.js +271 -0
  55. package/dist/esm-node/ultramodern-workspace/codesmith.js +1 -0
  56. package/dist/esm-node/ultramodern-workspace/contracts.js +124 -603
  57. package/dist/esm-node/ultramodern-workspace/demo-components.js +26 -33
  58. package/dist/esm-node/ultramodern-workspace/descriptors.js +2 -2
  59. package/dist/esm-node/ultramodern-workspace/effect-api.js +230 -100
  60. package/dist/esm-node/ultramodern-workspace/fs-io.js +116 -2
  61. package/dist/esm-node/ultramodern-workspace/generation-result.js +2 -2
  62. package/dist/esm-node/ultramodern-workspace/index.js +1 -0
  63. package/dist/esm-node/ultramodern-workspace/mf-validation.js +517 -0
  64. package/dist/esm-node/ultramodern-workspace/module-federation.js +49 -21
  65. package/dist/esm-node/ultramodern-workspace/package-json.js +60 -20
  66. package/dist/esm-node/ultramodern-workspace/policy.js +2 -2
  67. package/dist/esm-node/ultramodern-workspace/public-api.js +1 -0
  68. package/dist/esm-node/ultramodern-workspace/versions.js +3 -1
  69. package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +78 -26
  70. package/dist/esm-node/ultramodern-workspace/write-workspace.js +67 -27
  71. package/dist/types/locale/en.d.ts +10 -0
  72. package/dist/types/locale/index.d.ts +20 -0
  73. package/dist/types/locale/zh.d.ts +10 -0
  74. package/dist/types/ultramodern-tooling/commands.d.ts +1 -0
  75. package/dist/types/ultramodern-tooling/config.d.ts +43 -0
  76. package/dist/types/ultramodern-workspace/add-vertical.d.ts +5 -2
  77. package/dist/types/ultramodern-workspace/bridge-config.d.ts +64 -0
  78. package/dist/types/ultramodern-workspace/codesmith.d.ts +1 -0
  79. package/dist/types/ultramodern-workspace/contracts.d.ts +2 -17
  80. package/dist/types/ultramodern-workspace/descriptors.d.ts +1 -1
  81. package/dist/types/ultramodern-workspace/fs-io.d.ts +1 -0
  82. package/dist/types/ultramodern-workspace/index.d.ts +2 -0
  83. package/dist/types/ultramodern-workspace/mf-validation.d.ts +27 -0
  84. package/dist/types/ultramodern-workspace/module-federation.d.ts +1 -0
  85. package/dist/types/ultramodern-workspace/package-json.d.ts +5 -3
  86. package/dist/types/ultramodern-workspace/public-api.d.ts +2 -0
  87. package/dist/types/ultramodern-workspace/types.d.ts +2 -0
  88. package/dist/types/ultramodern-workspace/versions.d.ts +2 -0
  89. package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +2 -7
  90. package/dist/types/ultramodern-workspace/write-workspace.d.ts +4 -2
  91. package/package.json +5 -3
  92. package/template-workspace/{.agents → .codex}/skills-lock.json +12 -12
  93. package/template-workspace/.gitignore.handlebars +3 -0
  94. package/template-workspace/AGENTS.md.handlebars +11 -5
  95. package/template-workspace/README.md.handlebars +15 -12
  96. package/template-workspace/oxfmt.config.ts +1 -0
  97. package/template-workspace/oxlint.config.ts +1 -0
  98. package/template-workspace/patches/@tanstack__router-core@1.171.13.patch +51 -0
  99. package/template-workspace/pnpm-workspace.yaml.handlebars +12 -0
  100. package/template-workspace/scripts/bootstrap-agent-skills.mjs +96 -69
  101. package/templates/app/shell-frame.tsx +1 -2
  102. package/templates/app/ultramodern-route-head.tsx.handlebars +5 -6
  103. package/templates/workspace-scripts/assert-mf-types.mjs.handlebars +59 -7
  104. package/templates/workspace-scripts/check-ultramodern-api-boundaries.mjs +339 -0
  105. package/templates/workspace-scripts/generate-public-surface-assets.mjs +245 -8
  106. package/templates/workspace-scripts/proof-cloudflare-version.mjs +276 -8
  107. package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +35 -10
  108. package/templates/workspace-scripts/ultramodern-performance-readiness.mjs +164 -1
  109. package/templates/workspace-scripts/ultramodern-typecheck.mjs +4 -2
  110. package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +949 -63
  111. /package/template-workspace/{.agents → .codex}/rstackjs-agent-skills-LICENSE +0 -0
  112. /package/template-workspace/{.agents → .codex}/skills/rsbuild-best-practices/SKILL.md +0 -0
  113. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/SKILL.md +0 -0
  114. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/command-map.md +0 -0
  115. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/common-analysis-patterns.md +0 -0
  116. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-common.md +0 -0
  117. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-rspack.md +0 -0
  118. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-webpack.md +0 -0
  119. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor.md +0 -0
  120. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/rsdoctor-data-types.md +0 -0
  121. /package/template-workspace/{.agents → .codex}/skills/rslib-best-practices/SKILL.md +0 -0
  122. /package/template-workspace/{.agents → .codex}/skills/rslib-modern-package/SKILL.md +0 -0
  123. /package/template-workspace/{.agents → .codex}/skills/rspack-best-practices/SKILL.md +0 -0
  124. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/SKILL.md +0 -0
  125. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/bottlenecks.md +0 -0
  126. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/tracing-guide.md +0 -0
  127. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/scripts/analyze_trace.js +0 -0
  128. /package/template-workspace/{.agents → .codex}/skills/rstest-best-practices/SKILL.md +0 -0
@@ -8,16 +8,23 @@ function createAppModernConfig(scope, app) {
8
8
  const bffImport = appHasEffectApi(app) ? "import { bffPlugin } from '@modern-js/plugin-bff';\n" : '';
9
9
  const bffConfig = appHasEffectApi(app) ? ` bff: {
10
10
  effect: {
11
- entry: './api/effect/index',
11
+ entry: './api/index',
12
12
  openapi: {
13
13
  path: '/openapi.json',
14
14
  },
15
+ strictEffectApproach: true,
15
16
  },
16
17
  prefix: '${effectApiPrefix(app)}',
17
18
  runtimeFramework: 'effect',
18
19
  },
19
20
  ` : '';
20
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;`;
21
28
  return `// @effect-diagnostics processEnv:off
22
29
  import {
23
30
  appTools,
@@ -64,6 +71,8 @@ const configuredSiteUrl = envValue('MODERN_PUBLIC_SITE_URL');
64
71
  const configuredCloudflareUrl = envValue('${createCloudflarePublicUrlEnv(app)}');
65
72
  const configuredUltramodernAssetPrefix = envValue('ULTRAMODERN_ASSET_PREFIX');
66
73
  const configuredModernAssetPrefix = envValue('MODERN_ASSET_PREFIX');
74
+ const moduleFederationDevServerOrigin =
75
+ envValue('ULTRAMODERN_MF_DEV_ORIGIN') || 'http://localhost:${shellApp.port}';
67
76
  const cloudflareWorkersDevSubdomain = envValue(
68
77
  'ULTRAMODERN_CLOUDFLARE_WORKERS_DEV_SUBDOMAIN',
69
78
  );
@@ -78,12 +87,12 @@ const siteUrl =
78
87
  configuredCloudflareUrl ||
79
88
  inferredCloudflareUrl ||
80
89
  \`http://localhost:\${port}\`;
81
- // Asset loading is intentionally independent from the canonical site URL and
82
- // deployment public URL. Without an explicit asset prefix, assets stay
83
- // origin-relative so self-hosted apps, tunnels, and reverse proxies never leak
84
- // 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.
85
94
  const assetPrefix =
86
- configuredModernAssetPrefix || configuredUltramodernAssetPrefix || '/';
95
+ configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix;
87
96
 
88
97
  if (
89
98
  cloudflareDeployEnabled &&
@@ -187,6 +196,9 @@ ${bffPluginEntry} moduleFederationPlugin(),
187
196
  },
188
197
  mainEntryName: 'index',
189
198
  },
199
+ splitChunks: {
200
+ chunks: 'async',
201
+ },
190
202
  tools: {
191
203
  autoprefixer: {
192
204
  overrideBrowserslist: ['defaults'],
@@ -195,12 +207,14 @@ ${bffPluginEntry} moduleFederationPlugin(),
195
207
  chain.output
196
208
  .uniqueName('${createRspackUniqueName(app)}')
197
209
  .chunkLoadingGlobal('${createRspackChunkLoadingGlobal(app)}');
198
- chain.ignoreWarnings([
199
- {
200
- message: /the request of a dependency is an expression/u,
201
- module: /modern-js-plugin-i18n/u,
202
- },
203
- ]);
210
+ },
211
+ devServer: {
212
+ headers: {
213
+ 'Access-Control-Allow-Headers':
214
+ 'Accept, Authorization, Content-Type, X-Requested-With',
215
+ 'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
216
+ 'Access-Control-Allow-Origin': moduleFederationDevServerOrigin,
217
+ },
204
218
  },
205
219
  },
206
220
  },
@@ -222,11 +236,6 @@ function createSharedModuleFederationConfig() {
222
236
  singleton: true,
223
237
  treeShaking: false,
224
238
  },
225
- '@modern-js/plugin-i18n/runtime': {
226
- requiredVersion: pluginI18nVersion,
227
- singleton: true,
228
- treeShaking: false,
229
- },
230
239
  '@modern-js/plugin-tanstack/runtime': {
231
240
  requiredVersion: pluginTanstackVersion,
232
241
  singleton: true,
@@ -330,6 +339,7 @@ function createShellModuleFederationConfig(scope, remotes = []) {
330
339
  verticalRefs: remotes.map((remote)=>remote.id)
331
340
  };
332
341
  return `// @effect-diagnostics nodeBuiltinImport:off processEnv:off
342
+ // ultramodern-mf: host-only
333
343
  import { createRequire } from 'node:module';
334
344
  import { createModuleFederationConfig } from '@module-federation/modern-js-v3';
335
345
  import { dependencies } from './package.json';
@@ -342,7 +352,9 @@ const reactVersion = (require('react/package.json') as { version: string }).vers
342
352
  const reactDomVersion = (require('react-dom/package.json') as { version: string }).version;
343
353
 
344
354
  ${createModuleFederationRemoteUrlHelpers(shellHost, remotes)}
345
- export default createModuleFederationConfig({
355
+ const moduleFederationConfig: Parameters<
356
+ typeof createModuleFederationConfig
357
+ >[0] = createModuleFederationConfig({
346
358
  bridge: {
347
359
  enableBridgeRouter: false,
348
360
  },
@@ -354,12 +366,15 @@ export default createModuleFederationConfig({
354
366
  generateTypes: {
355
367
  compilerInstance: 'tsgo',
356
368
  },
369
+ tsConfigPath: './tsconfig.mf-types.json',
357
370
  },
358
371
  filename: 'remoteEntry.js',
359
372
  name: '${shellApp.mfName}',
360
373
  ${createModuleFederationRemotesConfig(scope, shellHost, remotes)}${createSharedModuleFederationConfig()},
361
374
  treeShakingSharedExcludePlugins: ['RspackModuleFederationPlugin'],
362
375
  });
376
+
377
+ export default moduleFederationConfig;
363
378
  `;
364
379
  }
365
380
  function createBuildMarker(scope, app) {
@@ -381,10 +396,18 @@ export const ultramodernUiMarker = {
381
396
 
382
397
  export const ultramodernApiMarker = {
383
398
  ...ultramodernVerticalIdentity,
384
- surface: 'effect-bff',
399
+ surface: 'api',
385
400
  } as const;
386
401
  `;
387
402
  }
403
+ function createUltramodernBuildReexportModule() {
404
+ return `export {
405
+ ultramodernApiMarker,
406
+ ultramodernUiMarker,
407
+ ultramodernVerticalIdentity,
408
+ } from '../shared/ultramodern-build';
409
+ `;
410
+ }
388
411
  function createRemoteModuleFederationConfig(scope, app, remotes = []) {
389
412
  const exposes = formatTsObjectLiteral(app.exposes ?? {});
390
413
  return `// @effect-diagnostics nodeBuiltinImport:off
@@ -400,7 +423,9 @@ const reactVersion = (require('react/package.json') as { version: string }).vers
400
423
  const reactDomVersion = (require('react-dom/package.json') as { version: string }).version;
401
424
 
402
425
  ${createModuleFederationRemoteUrlHelpers(app, remotes)}
403
- export default createModuleFederationConfig({
426
+ const moduleFederationConfig: Parameters<
427
+ typeof createModuleFederationConfig
428
+ >[0] = createModuleFederationConfig({
404
429
  bridge: {
405
430
  enableBridgeRouter: false,
406
431
  },
@@ -412,6 +437,7 @@ export default createModuleFederationConfig({
412
437
  generateTypes: {
413
438
  compilerInstance: 'tsgo',
414
439
  },
440
+ tsConfigPath: './tsconfig.mf-types.json',
415
441
  },
416
442
  exposes: ${exposes},
417
443
  filename: 'remoteEntry.js',
@@ -419,6 +445,8 @@ export default createModuleFederationConfig({
419
445
  ${createModuleFederationRemotesConfig(scope, app, remotes)}${createSharedModuleFederationConfig()},
420
446
  treeShakingSharedExcludePlugins: ['RspackModuleFederationPlugin'],
421
447
  });
448
+
449
+ export default moduleFederationConfig;
422
450
  `;
423
451
  }
424
- export { createAppModernConfig, createBuildMarker, createModuleFederationRemoteUrlHelpers, createModuleFederationRemotesConfig, createRemoteModuleFederationConfig, createSharedModuleFederationConfig, createShellModuleFederationConfig, createUltramodernBuildModule, formatTsObjectLiteral };
452
+ export { createAppModernConfig, createBuildMarker, createModuleFederationRemoteUrlHelpers, createModuleFederationRemotesConfig, createRemoteModuleFederationConfig, createSharedModuleFederationConfig, createShellModuleFederationConfig, createUltramodernBuildModule, createUltramodernBuildReexportModule, formatTsObjectLiteral };
@@ -80,7 +80,7 @@ const effectDiagnostics = [
80
80
  'unnecessaryPipe',
81
81
  'unnecessaryPipeChain'
82
82
  ];
83
- function appDependencies(scope, packageSource, app, remotes = []) {
83
+ function appDependencies(scope, packageSource, app, remotes = [], bridge) {
84
84
  const dependencies = {
85
85
  '@modern-js/plugin-tanstack': modernPackageSpecifier('@modern-js/plugin-tanstack', packageSource),
86
86
  '@modern-js/plugin-i18n': modernPackageSpecifier('@modern-js/plugin-i18n', packageSource),
@@ -95,8 +95,10 @@ function appDependencies(scope, packageSource, app, remotes = []) {
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
  };
101
+ for (const dependency of bridge?.dependencies ?? [])dependencies[dependency] = WORKSPACE_PACKAGE_VERSION;
100
102
  if ('shell' === app.kind) {
101
103
  dependencies['@modern-js/plugin-bff'] = modernPackageSpecifier('@modern-js/plugin-bff', packageSource);
102
104
  for (const remote of verticalEffectApps(remotes))dependencies[packageName(scope, remote.packageSuffix)] = WORKSPACE_PACKAGE_VERSION;
@@ -123,12 +125,28 @@ function appDevDependencies(packageSource, enableTailwind) {
123
125
  wrangler: WRANGLER_VERSION
124
126
  };
125
127
  }
126
- function createRootPackageJson(scope, packageSource, remotes = []) {
128
+ function createRootPackageJson(scope, packageSource, remotes = [], bridge) {
127
129
  const shellFilter = `--filter ${packageName(scope, shellApp.packageSuffix)}`;
128
130
  const remoteFilters = remotes.map((remote)=>`--filter ${packageName(scope, remote.packageSuffix)}`);
129
131
  const remoteBuildPrefix = remotes.length > 0 ? 'ULTRAMODERN_ZEPHYR=false pnpm -r --filter "./verticals/*" run build && ' : '';
130
132
  const remoteCloudflareBuildPrefix = remotes.length > 0 ? 'pnpm -r --filter "./verticals/*" run cloudflare:build && ' : '';
131
133
  const remoteCloudflareDeployPrefix = remotes.length > 0 ? 'pnpm -r --filter "./verticals/*" run cloudflare:deploy && ' : '';
134
+ const generatedPackageTypecheck = 'pnpm -r --filter "./apps/*" --filter "./verticals/*" --filter "./packages/*" run typecheck';
135
+ const typecheck = bridge ? generatedPackageTypecheck : "node ./scripts/ultramodern-typecheck.mjs --build tsconfig.json";
136
+ const bridgeScripts = bridge ? {
137
+ ...Object.fromEntries(bridge.gates.map((gate)=>[
138
+ `bridge:${gate.name}`,
139
+ `${gate.cwd ? `cd ${gate.cwd} && ` : ''}${gate.command}`
140
+ ])),
141
+ 'bridge:check': bridge.gates.map((gate)=>`pnpm run bridge:${gate.name}`).join(' && ')
142
+ } : {};
143
+ const bridgeCheck = bridge ? ' && pnpm bridge:check' : '';
144
+ const workspacePackages = [
145
+ 'apps/*',
146
+ 'verticals/*',
147
+ 'packages/*',
148
+ ...bridge?.workspacePackages.map((entry)=>entry.pattern) ?? []
149
+ ];
132
150
  return {
133
151
  private: true,
134
152
  name: scope,
@@ -150,7 +168,7 @@ function createRootPackageJson(scope, packageSource, remotes = []) {
150
168
  'format:check': "oxfmt --check . '!repos/**'",
151
169
  lint: 'oxlint apps verticals packages',
152
170
  'lint:fix': 'oxlint apps verticals packages --fix',
153
- typecheck: "node ./scripts/ultramodern-typecheck.mjs --build tsconfig.json",
171
+ typecheck,
154
172
  'cloudflare:build': `${remoteCloudflareBuildPrefix}pnpm --filter "./apps/shell-super-app" run cloudflare:build && pnpm mf:types`,
155
173
  'cloudflare:deploy': `${remoteCloudflareDeployPrefix}pnpm --filter "./apps/shell-super-app" run cloudflare:deploy`,
156
174
  'cloudflare:proof': "node ./scripts/proof-cloudflare-version.mjs --out .codex/reports/cloudflare-version-proof/public-url-proof.json",
@@ -161,19 +179,17 @@ function createRootPackageJson(scope, packageSource, remotes = []) {
161
179
  'mf:types': "node ./scripts/assert-mf-types.mjs",
162
180
  'performance:readiness': "node ./scripts/ultramodern-performance-readiness.mjs",
163
181
  'contract:check': "node ./scripts/validate-ultramodern-workspace.mjs",
182
+ 'api:check': "node ./scripts/check-ultramodern-api-boundaries.mjs",
164
183
  'i18n:boundaries': "node ./scripts/check-ultramodern-i18n-boundaries.mjs",
184
+ ...bridgeScripts,
165
185
  postinstall: "oxfmt . '!repos/**' && node ./scripts/bootstrap-agent-skills.mjs --postinstall",
166
- check: 'pnpm format:check && pnpm lint && pnpm typecheck && pnpm skills:check && pnpm i18n:boundaries && pnpm contract:check && pnpm performance:readiness'
186
+ check: `pnpm format:check && pnpm lint && pnpm typecheck && pnpm skills:check && pnpm i18n:boundaries && pnpm api:check && pnpm contract:check && pnpm performance:readiness${bridgeCheck}`
167
187
  },
168
188
  engines: {
169
189
  node: '>=26',
170
190
  pnpm: '>=11'
171
191
  },
172
- workspaces: [
173
- 'apps/*',
174
- 'verticals/*',
175
- 'packages/*'
176
- ],
192
+ workspaces: workspacePackages,
177
193
  modernjs: {
178
194
  preset: 'presetUltramodern',
179
195
  workspace: 'ultramodern-superapp',
@@ -181,7 +197,7 @@ function createRootPackageJson(scope, packageSource, remotes = []) {
181
197
  ownership: './topology/ownership.json',
182
198
  packageSource: {
183
199
  strategy: packageSource.strategy,
184
- config: './.modernjs/ultramodern-package-source.json'
200
+ config: './.modernjs/ultramodern.json#packageSource'
185
201
  }
186
202
  },
187
203
  devDependencies: {
@@ -255,6 +271,10 @@ function createTsBuildInfoFile(packageDir) {
255
271
  const cacheKey = packageDir.replace(/[^a-zA-Z0-9._-]+/gu, '__');
256
272
  return `${relativeRootFor(packageDir)}/node_modules/.cache/tsgo/${cacheKey}.tsbuildinfo`;
257
273
  }
274
+ function createTsDeclarationOutDir(packageDir) {
275
+ const cacheKey = packageDir.replace(/[^a-zA-Z0-9._-]+/gu, '__');
276
+ return `${relativeRootFor(packageDir)}/node_modules/.cache/tsgo/declarations/${cacheKey}`;
277
+ }
258
278
  function createReferences(packageDir, references) {
259
279
  return [
260
280
  ...new Set(references)
@@ -268,16 +288,24 @@ function createPackageTsConfig(packageDir, options = {}) {
268
288
  } : options;
269
289
  const include = resolvedOptions.include ?? [
270
290
  'src',
291
+ 'locales/**/*.json',
271
292
  'modern.config.ts',
272
- 'module-federation.config.ts'
293
+ 'module-federation.config.ts',
294
+ 'package.json',
295
+ 'shared'
273
296
  ];
274
- if (resolvedOptions.includeApi) include.push('api', 'shared');
297
+ if (resolvedOptions.includeApi) include.push('api');
275
298
  const references = createReferences(packageDir, resolvedOptions.references ?? []);
276
299
  const tsconfig = {
277
300
  extends: `${relativeRootFor(packageDir)}/tsconfig.base.json`,
278
301
  compilerOptions: {
279
302
  composite: true,
303
+ declaration: true,
304
+ declarationMap: false,
305
+ emitDeclarationOnly: true,
280
306
  incremental: true,
307
+ noEmit: false,
308
+ outDir: createTsDeclarationOutDir(packageDir),
281
309
  tsBuildInfoFile: createTsBuildInfoFile(packageDir)
282
310
  },
283
311
  include
@@ -295,6 +323,18 @@ function createAppTsConfig(app, remotes = []) {
295
323
  references
296
324
  });
297
325
  }
326
+ function createAppMfTypesTsConfig(app) {
327
+ const exposedFiles = Object.values(app.exposes ?? {}).map((exposePath)=>exposePath.replace(/^\.\//u, ''));
328
+ return {
329
+ extends: './tsconfig.json',
330
+ include: [
331
+ ...new Set([
332
+ ...exposedFiles,
333
+ 'src/modern-app-env.d.ts'
334
+ ])
335
+ ]
336
+ };
337
+ }
298
338
  function createSharedPackageTsConfig(packageDir) {
299
339
  return createPackageTsConfig(packageDir, {
300
340
  include: [
@@ -315,7 +355,7 @@ function createRootTsConfig(apps = []) {
315
355
  ]
316
356
  };
317
357
  }
318
- function createAppPackage(scope, app, packageSource, enableTailwind, remotes = []) {
358
+ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [], bridge) {
319
359
  const publicSurfaceBuildCommand = createPublicSurfaceGenerationCommand(app, 'dist');
320
360
  const publicSurfaceCloudflareBuildCommand = createPublicSurfaceGenerationCommand(app, 'dist');
321
361
  const publicSurfaceCloudflareOutputCommand = createPublicSurfaceGenerationCommand(app, 'cloudflare');
@@ -343,19 +383,19 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
343
383
  appId: app.id,
344
384
  topology: `${relativeRootFor(app.directory)}/topology/reference-topology.json`,
345
385
  ...appHasEffectApi(app) ? {
346
- apiRuntime: 'effect-bff'
386
+ apiRuntime: 'effect'
347
387
  } : {}
348
388
  },
349
389
  'zephyr:dependencies': createZephyrDependencies(scope, app, remotes),
350
- dependencies: appDependencies(scope, packageSource, app, remotes),
390
+ dependencies: appDependencies(scope, packageSource, app, remotes, bridge),
351
391
  devDependencies: appDevDependencies(packageSource, enableTailwind)
352
392
  };
353
393
  if (appHasEffectApi(app)) Object.assign(packageExports, {
354
- './effect/client': `./src/effect/${app.effectApi.stem}-client.ts`,
355
- './shared/effect/api': './shared/effect/api.ts'
394
+ './api': './shared/api.ts',
395
+ './api/client': `./src/api/${app.effectApi.stem}-client.ts`
356
396
  });
357
397
  else if ('shell' === app.kind) Object.assign(packageExports, {
358
- './effect/clients': './src/effect/vertical-clients.ts'
398
+ './api/clients': './src/api/vertical-clients.ts'
359
399
  });
360
400
  if (Object.keys(packageExports).length > 0) packageJson.exports = packageExports;
361
401
  return packageJson;
@@ -387,4 +427,4 @@ function createSharedPackage(scope, id, description) {
387
427
  function createSharedContractsIndex() {
388
428
  return readFileTemplate('packages/shared-contracts-index.ts');
389
429
  }
390
- export { appDependencies, appDevDependencies, createAppPackage, createAppTsConfig, createEffectTsgoTypecheckCommand, createPackageTsConfig, createRootPackageJson, createRootTsConfig, createSharedContractsIndex, createSharedPackage, createSharedPackageTsConfig, createTsConfigBase, createZephyrDependencies, effectDiagnostics };
430
+ export { appDependencies, appDevDependencies, createAppMfTypesTsConfig, createAppPackage, createAppTsConfig, createEffectTsgoTypecheckCommand, createPackageTsConfig, createRootPackageJson, createRootTsConfig, createSharedContractsIndex, createSharedPackage, createSharedPackageTsConfig, createTsConfigBase, createZephyrDependencies, effectDiagnostics };
@@ -16,7 +16,7 @@ function createCloudflareProofRoute(app) {
16
16
  mfManifest: '/mf-manifest.json',
17
17
  locale: `/locales/en/${appI18nNamespace(app)}.json`,
18
18
  ...appHasEffectApi(app) ? {
19
- effectReadiness: `${effectApiPrefix(app)}/effect/${effectApiStem(app)}/readiness`
19
+ apiReadiness: `${effectApiPrefix(app)}/${effectApiStem(app)}/readiness`
20
20
  } : {}
21
21
  };
22
22
  }
@@ -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: {
@@ -1,2 +1,3 @@
1
1
  export { addUltramodernVertical, planUltramodernVertical } from "./add-vertical.js";
2
+ export { normalizeUltramodernBridgeConfig } from "./bridge-config.js";
2
3
  export { generateUltramodernWorkspace } from "./write-workspace.js";
@@ -1,4 +1,5 @@
1
1
  const TANSTACK_ROUTER_VERSION = '1.170.16';
2
+ const TANSTACK_ROUTER_CORE_VERSION = '1.171.13';
2
3
  const MODULE_FEDERATION_VERSION = '2.6.0';
3
4
  const ZEPHYR_RSPACK_PLUGIN_VERSION = '1.1.1';
4
5
  const ZEPHYR_AGENT_VERSION = '1.1.1';
@@ -28,8 +29,9 @@ const RSTACK_AGENT_SKILLS_COMMIT = '61c948b42512e223bad44b83af4080eba48b2677';
28
29
  const MODULE_FEDERATION_AGENT_SKILLS_COMMIT = '07bb5b6c43ad457609e00c081b72d4c42508ec76';
29
30
  const ultramodernWorkspaceVersions = {
30
31
  tanstackRouter: TANSTACK_ROUTER_VERSION,
32
+ tanstackRouterCore: TANSTACK_ROUTER_CORE_VERSION,
31
33
  moduleFederation: MODULE_FEDERATION_VERSION,
32
34
  tailwind: TAILWIND_VERSION,
33
35
  tailwindPostcss: TAILWIND_POSTCSS_VERSION
34
36
  };
35
- export { CLOUDFLARE_COMPATIBILITY_DATE, EFFECT_TSGO_VERSION, I18NEXT_VERSION, LEFTHOOK_VERSION, MODULE_FEDERATION_AGENT_SKILLS_COMMIT, MODULE_FEDERATION_VERSION, NODE_FETCH_VERSION, NODE_VERSION, OXFMT_VERSION, OXLINT_VERSION, PNPM_VERSION, POSTCSS_VERSION, REACT_DOM_VERSION, REACT_ROUTER_VERSION, REACT_VERSION, RSTACK_AGENT_SKILLS_COMMIT, TAILWIND_POSTCSS_VERSION, TAILWIND_VERSION, TANSTACK_ROUTER_VERSION, TYPESCRIPT_NATIVE_PREVIEW_VERSION, TYPESCRIPT_STABLE_VERSION, TYPESCRIPT_VERSION, TYPES_REACT_DOM_VERSION, TYPES_REACT_VERSION, ULTRACITE_VERSION, WRANGLER_VERSION, ZEPHYR_AGENT_VERSION, ZEPHYR_RSPACK_PLUGIN_VERSION, ultramodernWorkspaceVersions };
37
+ export { CLOUDFLARE_COMPATIBILITY_DATE, EFFECT_TSGO_VERSION, I18NEXT_VERSION, LEFTHOOK_VERSION, MODULE_FEDERATION_AGENT_SKILLS_COMMIT, MODULE_FEDERATION_VERSION, NODE_FETCH_VERSION, NODE_VERSION, OXFMT_VERSION, OXLINT_VERSION, PNPM_VERSION, POSTCSS_VERSION, REACT_DOM_VERSION, REACT_ROUTER_VERSION, REACT_VERSION, RSTACK_AGENT_SKILLS_COMMIT, TAILWIND_POSTCSS_VERSION, TAILWIND_VERSION, TANSTACK_ROUTER_CORE_VERSION, TANSTACK_ROUTER_VERSION, TYPESCRIPT_NATIVE_PREVIEW_VERSION, TYPESCRIPT_STABLE_VERSION, TYPESCRIPT_VERSION, TYPES_REACT_DOM_VERSION, TYPES_REACT_VERSION, ULTRACITE_VERSION, WRANGLER_VERSION, ZEPHYR_AGENT_VERSION, ZEPHYR_RSPACK_PLUGIN_VERSION, ultramodernWorkspaceVersions };
@@ -7,10 +7,73 @@ import { createCloudflareSecurityContract } from "./policy.js";
7
7
  import { publicSurfaceManagedSourceAssetPaths } from "./public-surface.js";
8
8
  import { createLocalisedUrlsMap, createRouteMetaFilePath, createRouteOwnedI18nPaths, createRoutePageFilePath } from "./routes.js";
9
9
  import { CLOUDFLARE_COMPATIBILITY_DATE, NODE_VERSION, PNPM_VERSION } from "./versions.js";
10
- function createAssertMfTypesScript(remotes = []) {
11
- return renderFileTemplate("workspace-scripts/assert-mf-types.mjs", {
12
- defaultAppDirsJson: JSON.stringify(remotes.map((remote)=>remote.directory), null, 2)
10
+ function createToolWrapperScript(command, extraArgs = []) {
11
+ const commandJson = JSON.stringify(command);
12
+ const extraArgsJson = JSON.stringify(extraArgs);
13
+ return `#!/usr/bin/env node
14
+ import { spawnSync } from 'node:child_process';
15
+ import path from 'node:path';
16
+ import { fileURLToPath } from 'node:url';
17
+
18
+ const createBin = process.env.ULTRAMODERN_CREATE_BIN;
19
+ const forwardedArgs = process.argv.slice(2);
20
+ const workspaceRoot =
21
+ process.env.ULTRAMODERN_WORKSPACE_ROOT ??
22
+ path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
23
+ const ultramodernArgs = ['ultramodern', ${commandJson}, ...${extraArgsJson}, ...forwardedArgs];
24
+ const result = createBin
25
+ ? spawnSync(process.execPath, [createBin, ...ultramodernArgs], {
26
+ env: { ...process.env, ULTRAMODERN_WORKSPACE_ROOT: workspaceRoot },
27
+ stdio: 'inherit',
28
+ })
29
+ : spawnSync('modern-js-create', ultramodernArgs, {
30
+ env: { ...process.env, ULTRAMODERN_WORKSPACE_ROOT: workspaceRoot },
31
+ shell: process.platform === 'win32',
32
+ stdio: 'inherit',
13
33
  });
34
+
35
+ if (result.error) {
36
+ console.error(result.error.message);
37
+ process.exit(1);
38
+ }
39
+
40
+ process.exit(result.status ?? 1);
41
+ `;
42
+ }
43
+ function createSkillsToolWrapperScript() {
44
+ return `#!/usr/bin/env node
45
+ import { spawnSync } from 'node:child_process';
46
+ import path from 'node:path';
47
+ import { fileURLToPath } from 'node:url';
48
+
49
+ const createBin = process.env.ULTRAMODERN_CREATE_BIN;
50
+ const forwardedArgs = process.argv.slice(2);
51
+ const workspaceRoot =
52
+ process.env.ULTRAMODERN_WORKSPACE_ROOT ??
53
+ path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
54
+ const checkOnly = forwardedArgs.includes('--check');
55
+ const skillArgs = checkOnly
56
+ ? ['skills', 'check', ...forwardedArgs.filter(arg => arg !== '--check')]
57
+ : ['skills', 'install', ...forwardedArgs];
58
+ const ultramodernArgs = ['ultramodern', ...skillArgs];
59
+ const result = createBin
60
+ ? spawnSync(process.execPath, [createBin, ...ultramodernArgs], {
61
+ env: { ...process.env, ULTRAMODERN_WORKSPACE_ROOT: workspaceRoot },
62
+ stdio: 'inherit',
63
+ })
64
+ : spawnSync('modern-js-create', ultramodernArgs, {
65
+ env: { ...process.env, ULTRAMODERN_WORKSPACE_ROOT: workspaceRoot },
66
+ shell: process.platform === 'win32',
67
+ stdio: 'inherit',
68
+ });
69
+
70
+ if (result.error) {
71
+ console.error(result.error.message);
72
+ process.exit(1);
73
+ }
74
+
75
+ process.exit(result.status ?? 1);
76
+ `;
14
77
  }
15
78
  function createWorkspaceValidationScript(scope, enableTailwind, remotes = []) {
16
79
  const verticals = remotes.filter(appHasEffectApi).map((remote)=>({
@@ -64,33 +127,22 @@ function createWorkspaceValidationScript(scope, enableTailwind, remotes = []) {
64
127
  function createWorkspaceI18nBoundaryValidationScript() {
65
128
  return readFileTemplate("workspace-scripts/check-ultramodern-i18n-boundaries.mjs");
66
129
  }
67
- function createPublicSurfaceAssetsScript() {
68
- return readFileTemplate("workspace-scripts/generate-public-surface-assets.mjs");
69
- }
70
- function createCloudflareProofHelperScript() {
71
- return readFileTemplate("workspace-scripts/ultramodern-cloudflare-proof.mjs");
72
- }
73
- function createCloudflareVersionProofScript() {
74
- return readFileTemplate("workspace-scripts/proof-cloudflare-version.mjs");
130
+ function createWorkspaceApiBoundaryValidationScript() {
131
+ return readFileTemplate("workspace-scripts/check-ultramodern-api-boundaries.mjs");
75
132
  }
76
133
  function createPerformanceReadinessConfigScript() {
77
134
  return readFileTemplate("workspace-scripts/ultramodern-performance-readiness.config.mjs");
78
135
  }
79
- function createPerformanceReadinessScript() {
80
- return readFileTemplate("workspace-scripts/ultramodern-performance-readiness.mjs");
81
- }
82
- function createUltramodernTypecheckScript() {
83
- return readFileTemplate("workspace-scripts/ultramodern-typecheck.mjs");
84
- }
85
- function writeGeneratedWorkspaceScripts(targetDir, scope, enableTailwind, remotes = []) {
86
- writeFileReplacing(targetDir, "scripts/assert-mf-types.mjs", createAssertMfTypesScript(remotes));
87
- writeFileReplacing(targetDir, "scripts/validate-ultramodern-workspace.mjs", createWorkspaceValidationScript(scope, enableTailwind, remotes));
136
+ function writeGeneratedWorkspaceScripts(targetDir, _scope, _enableTailwind, _remotes = []) {
137
+ writeFileReplacing(targetDir, "scripts/assert-mf-types.mjs", createToolWrapperScript('mf-types'));
138
+ writeFileReplacing(targetDir, "scripts/validate-ultramodern-workspace.mjs", createToolWrapperScript('validate'));
88
139
  writeFileReplacing(targetDir, "scripts/check-ultramodern-i18n-boundaries.mjs", createWorkspaceI18nBoundaryValidationScript());
89
- writeFileReplacing(targetDir, "scripts/generate-public-surface-assets.mjs", createPublicSurfaceAssetsScript());
90
- writeFileReplacing(targetDir, "scripts/ultramodern-cloudflare-proof.mjs", createCloudflareProofHelperScript());
91
- writeFileReplacing(targetDir, "scripts/proof-cloudflare-version.mjs", createCloudflareVersionProofScript());
140
+ writeFileReplacing(targetDir, "scripts/check-ultramodern-api-boundaries.mjs", createWorkspaceApiBoundaryValidationScript());
141
+ writeFileReplacing(targetDir, "scripts/generate-public-surface-assets.mjs", createToolWrapperScript('public-surface'));
142
+ writeFileReplacing(targetDir, "scripts/proof-cloudflare-version.mjs", createToolWrapperScript('cloudflare-proof'));
92
143
  writeFileReplacing(targetDir, "scripts/ultramodern-performance-readiness.config.mjs", createPerformanceReadinessConfigScript());
93
- writeFileReplacing(targetDir, "scripts/ultramodern-performance-readiness.mjs", createPerformanceReadinessScript());
94
- writeFileReplacing(targetDir, "scripts/ultramodern-typecheck.mjs", createUltramodernTypecheckScript());
144
+ writeFileReplacing(targetDir, "scripts/ultramodern-performance-readiness.mjs", createToolWrapperScript('performance-readiness'));
145
+ writeFileReplacing(targetDir, "scripts/ultramodern-typecheck.mjs", createToolWrapperScript('typecheck'));
146
+ writeFileReplacing(targetDir, "scripts/bootstrap-agent-skills.mjs", createSkillsToolWrapperScript());
95
147
  }
96
- export { createAssertMfTypesScript, createCloudflareProofHelperScript, createCloudflareVersionProofScript, createPerformanceReadinessConfigScript, createPerformanceReadinessScript, createPublicSurfaceAssetsScript, createUltramodernTypecheckScript, createWorkspaceI18nBoundaryValidationScript, createWorkspaceValidationScript, writeGeneratedWorkspaceScripts };
148
+ export { createPerformanceReadinessConfigScript, createWorkspaceApiBoundaryValidationScript, createWorkspaceI18nBoundaryValidationScript, createWorkspaceValidationScript, writeGeneratedWorkspaceScripts };