@bleedingdev/modern-js-create 3.4.0-ultramodern.9 → 3.5.0-ultramodern.1

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 +49 -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 +431 -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 +128 -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 +39 -12
  19. package/dist/cjs/ultramodern-workspace/overlays.cjs +2 -2
  20. package/dist/cjs/ultramodern-workspace/package-json.cjs +58 -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 +15 -0
  25. package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +120 -50
  26. package/dist/cjs/ultramodern-workspace/write-workspace.cjs +64 -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 +378 -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 +130 -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 +40 -13
  44. package/dist/esm/ultramodern-workspace/overlays.js +2 -2
  45. package/dist/esm/ultramodern-workspace/package-json.js +57 -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 +7 -1
  50. package/dist/esm/ultramodern-workspace/workspace-scripts.js +108 -34
  51. package/dist/esm/ultramodern-workspace/write-workspace.js +66 -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 +379 -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 +130 -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 +40 -13
  69. package/dist/esm-node/ultramodern-workspace/overlays.js +2 -2
  70. package/dist/esm-node/ultramodern-workspace/package-json.js +57 -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 +7 -1
  75. package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +108 -34
  76. package/dist/esm-node/ultramodern-workspace/write-workspace.js +66 -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 +6 -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 +55 -13
  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 +7 -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 +366 -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 +842 -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
@@ -4,18 +4,255 @@ import path from 'node:path';
4
4
  import { fileURLToPath, pathToFileURL } from 'node:url';
5
5
 
6
6
  const workspaceRoot = path.resolve(
7
- path.dirname(fileURLToPath(import.meta.url)),
8
- '..',
9
- );
10
- const contractPath = path.join(
11
- workspaceRoot,
12
- '.modernjs/ultramodern-generated-contract.json',
7
+ process.env.ULTRAMODERN_WORKSPACE_ROOT ??
8
+ path.join(path.dirname(fileURLToPath(import.meta.url)), '..'),
13
9
  );
10
+ const compactConfigPath = path.join(workspaceRoot, '.modernjs/ultramodern.json');
14
11
 
15
12
  function readJson(filePath) {
16
13
  return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
17
14
  }
18
15
 
16
+ function toKebabCase(value) {
17
+ return String(value)
18
+ .trim()
19
+ .replace(/([a-z0-9])([A-Z])/gu, '$1-$2')
20
+ .replace(/[^a-zA-Z0-9._-]+/gu, '-')
21
+ .replace(/[._]+/gu, '-')
22
+ .toLowerCase()
23
+ .replace(/-+/gu, '-')
24
+ .replace(/^-+|-+$/gu, '');
25
+ }
26
+
27
+ function toEnvSegment(value) {
28
+ return toKebabCase(value).replace(/-/gu, '_').toUpperCase();
29
+ }
30
+
31
+ function normalizeRelativePath(value) {
32
+ return String(value ?? '').replace(/\\/gu, '/').replace(/^\.\/+/u, '');
33
+ }
34
+
35
+ function appNamespace(app) {
36
+ return app.kind === 'shell' ? 'shell' : (app.domain ?? app.id);
37
+ }
38
+
39
+ function defaultPortEnv(app) {
40
+ return app.kind === 'shell'
41
+ ? 'SHELL_SUPER_APP_PORT'
42
+ : `VERTICAL_${toEnvSegment(app.domain ?? app.id)}_PORT`;
43
+ }
44
+
45
+ function defaultPort(app) {
46
+ return app.kind === 'shell' ? 3020 : 3030;
47
+ }
48
+
49
+ function normalizeCompactApp(rawApp) {
50
+ const id = String(rawApp.id);
51
+ const kind = rawApp.kind === 'vertical' ? 'vertical' : 'shell';
52
+ const appPath =
53
+ typeof rawApp.path === 'string'
54
+ ? normalizeRelativePath(rawApp.path)
55
+ : kind === 'shell'
56
+ ? 'apps/shell-super-app'
57
+ : `verticals/${toKebabCase(id)}`;
58
+ const packageSuffix =
59
+ typeof rawApp.packageSuffix === 'string'
60
+ ? rawApp.packageSuffix
61
+ : appPath.split('/').at(-1) ?? id;
62
+ const domain =
63
+ typeof rawApp.domain === 'string'
64
+ ? rawApp.domain
65
+ : kind === 'vertical'
66
+ ? packageSuffix
67
+ : undefined;
68
+ const moduleFederation =
69
+ rawApp.moduleFederation && typeof rawApp.moduleFederation === 'object'
70
+ ? rawApp.moduleFederation
71
+ : {};
72
+
73
+ return {
74
+ id,
75
+ kind,
76
+ path: appPath,
77
+ packageSuffix,
78
+ domain,
79
+ port:
80
+ typeof rawApp.port === 'number'
81
+ ? rawApp.port
82
+ : defaultPort({ id, kind, domain }),
83
+ portEnv:
84
+ typeof rawApp.portEnv === 'string'
85
+ ? rawApp.portEnv
86
+ : defaultPortEnv({ id, kind, domain }),
87
+ mfName:
88
+ typeof moduleFederation.name === 'string'
89
+ ? moduleFederation.name
90
+ : kind === 'shell'
91
+ ? 'shellSuperApp'
92
+ : `vertical${toKebabCase(domain ?? id)
93
+ .split('-')
94
+ .filter(Boolean)
95
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
96
+ .join('')}`,
97
+ exposes: Array.isArray(moduleFederation.exposes)
98
+ ? moduleFederation.exposes.filter(expose => typeof expose === 'string')
99
+ : [],
100
+ verticalRefs: Array.isArray(moduleFederation.verticalRefs)
101
+ ? moduleFederation.verticalRefs.filter(ref => typeof ref === 'string')
102
+ : [],
103
+ marker: {
104
+ appId: id,
105
+ },
106
+ routes:
107
+ rawApp.routes && typeof rawApp.routes === 'object'
108
+ ? rawApp.routes
109
+ : undefined,
110
+ api:
111
+ rawApp.api && typeof rawApp.api === 'object'
112
+ ? {
113
+ stem:
114
+ typeof rawApp.api.stem === 'string'
115
+ ? rawApp.api.stem
116
+ : domain ?? id,
117
+ prefix:
118
+ typeof rawApp.api.prefix === 'string'
119
+ ? rawApp.api.prefix
120
+ : `/${domain ?? id}-api`,
121
+ }
122
+ : undefined,
123
+ };
124
+ }
125
+
126
+ function createRouteOwnedEntries(app) {
127
+ const namespace = appNamespace(app);
128
+ const base = {
129
+ descriptionKey: `${namespace}.seo.description`,
130
+ mfBoundaryId: app.mfName,
131
+ namespace,
132
+ ownerAppId: app.id,
133
+ public: false,
134
+ indexable: false,
135
+ publicSurface: 'private-app-screen',
136
+ };
137
+
138
+ return [
139
+ {
140
+ ...base,
141
+ canonicalPath: '/',
142
+ id: app.kind === 'shell' ? 'shell-home' : `${app.id}-home`,
143
+ localisedPaths: {
144
+ cs: '/',
145
+ en: '/',
146
+ },
147
+ titleKey: app.kind === 'shell' ? 'shell.title' : `${namespace}.title`,
148
+ },
149
+ ];
150
+ }
151
+
152
+ function createPublicRoutes(app) {
153
+ return createRouteOwnedEntries(app)
154
+ .filter(route => route.public && route.indexable)
155
+ .map(route => ({
156
+ canonicalPath: route.canonicalPath,
157
+ id: route.id,
158
+ localisedPaths: route.localisedPaths,
159
+ namespace: route.namespace,
160
+ ownerAppId: route.ownerAppId,
161
+ descriptionKey: route.descriptionKey,
162
+ titleKey: route.titleKey,
163
+ }));
164
+ }
165
+
166
+ function createPublicSurface(app) {
167
+ const publicRoutes = createPublicRoutes(app);
168
+ const basePublicSurface = {
169
+ authoring: 'colocated-route-meta',
170
+ artifactLifecycle: 'build-and-deploy-output',
171
+ generatedManifest: './src/routes/ultramodern-route-metadata',
172
+ source: 'route-owned-public-routes',
173
+ metadataExport: './src/routes/ultramodern-route-metadata',
174
+ generator: 'scripts/generate-public-surface-assets.mts',
175
+ outputRoot: 'dist/public',
176
+ cloudflareOutputRoot: '.output/public',
177
+ privateRoutePolicy: 'omit-from-generated-public-surface',
178
+ files:
179
+ publicRoutes.length > 0
180
+ ? ['robots.txt', 'sitemap.xml', 'site.webmanifest']
181
+ : ['robots.txt'],
182
+ omittedByDefault: ['api-catalog.json', 'llms.txt', 'security.txt'],
183
+ languages: ['en', 'cs'],
184
+ contentExpansion: {
185
+ authoring: 'route-owned-esm-provider',
186
+ defaultProviderFile: 'route.sitemap.mjs',
187
+ entryExport: 'default-or-entries',
188
+ paramsSource: 'params-or-localeParams',
189
+ draftPolicy: 'omit-draft-by-default',
190
+ indexablePolicy: 'omit-indexable-false',
191
+ lifecycle: 'executed-during-public-surface-generation',
192
+ },
193
+ contentSources: [],
194
+ publicRoutes,
195
+ routeEntries: [],
196
+ concreteUrlPaths: [],
197
+ };
198
+
199
+ return app.routes?.publicSurface &&
200
+ typeof app.routes.publicSurface === 'object'
201
+ ? {
202
+ ...basePublicSurface,
203
+ ...app.routes.publicSurface,
204
+ }
205
+ : basePublicSurface;
206
+ }
207
+
208
+ function createCloudflareDeploy(config, app) {
209
+ const packageScope =
210
+ typeof config.workspace?.packageScope === 'string'
211
+ ? config.workspace.packageScope
212
+ : path.basename(workspaceRoot);
213
+ const compatibilityDate =
214
+ typeof config.deploy?.worker?.compatibilityDate === 'string'
215
+ ? config.deploy.worker.compatibilityDate
216
+ : '2026-06-02';
217
+ return {
218
+ workerName: `${toKebabCase(packageScope)}-${app.packageSuffix}`.slice(0, 63),
219
+ publicUrlEnv: `ULTRAMODERN_PUBLIC_URL_${toEnvSegment(app.id)}`,
220
+ compatibilityDate,
221
+ compatibilityFlags: ['nodejs_compat', 'global_fetch_strictly_public'],
222
+ };
223
+ }
224
+
225
+ function synthesizeContractFromCompactConfig(config) {
226
+ const apps = Array.isArray(config.topology?.apps)
227
+ ? config.topology.apps.map(normalizeCompactApp)
228
+ : [];
229
+
230
+ return {
231
+ sourcePath: compactConfigPath,
232
+ apps: apps.map(app => ({
233
+ ...app,
234
+ deploy: {
235
+ cloudflare: createCloudflareDeploy(config, app),
236
+ },
237
+ routes: {
238
+ publicSurface: createPublicSurface(app),
239
+ },
240
+ })),
241
+ };
242
+ }
243
+
244
+ function readGeneratedContractView() {
245
+ if (fs.existsSync(compactConfigPath)) {
246
+ return synthesizeContractFromCompactConfig(readJson(compactConfigPath));
247
+ }
248
+ throw new Error(
249
+ `Missing UltraModern config. Expected ${path.relative(
250
+ workspaceRoot,
251
+ compactConfigPath,
252
+ )}.`,
253
+ );
254
+ }
255
+
19
256
  function parseArgs(argv) {
20
257
  const parsed = {
21
258
  appId: undefined,
@@ -52,7 +289,7 @@ function parseArgs(argv) {
52
289
 
53
290
  function printHelp() {
54
291
  process.stdout.write(`Usage:
55
- node scripts/generate-public-surface-assets.mjs --app shell-super-app [--target dist|cloudflare] [--require-public-origin]
292
+ node scripts/generate-public-surface-assets.mts --app shell-super-app [--target dist|cloudflare] [--require-public-origin]
56
293
 
57
294
  Set each app's production URL using the contract env key, for example:
58
295
  ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP=https://example.com
@@ -517,10 +754,10 @@ try {
517
754
  printHelp();
518
755
  process.exit(0);
519
756
  }
520
- const contract = readJson(contractPath);
757
+ const contract = readGeneratedContractView();
521
758
  const app = contract.apps?.find(candidate => candidate.id === args.appId);
522
759
  if (!app) {
523
- throw new Error(`Unknown app in generated contract: ${args.appId}`);
760
+ throw new Error(`Unknown app in UltraModern config: ${args.appId}`);
524
761
  }
525
762
  await generatePublicSurfaceAssets(app, args.target, args.requirePublicOrigin);
526
763
  } catch (error) {
@@ -1,17 +1,15 @@
1
1
  #!/usr/bin/env node
2
+ import crypto from 'node:crypto';
2
3
  import fs from 'node:fs';
3
4
  import path from 'node:path';
4
5
  import { fileURLToPath } from 'node:url';
5
6
  import { validateApp } from './ultramodern-cloudflare-proof.mjs';
6
7
 
7
8
  const workspaceRoot = path.resolve(
8
- path.dirname(fileURLToPath(import.meta.url)),
9
- '..',
10
- );
11
- const contractPath = path.join(
12
- workspaceRoot,
13
- '.modernjs/ultramodern-generated-contract.json',
9
+ process.env.ULTRAMODERN_WORKSPACE_ROOT ??
10
+ path.join(path.dirname(fileURLToPath(import.meta.url)), '..'),
14
11
  );
12
+ const compactConfigPath = path.join(workspaceRoot, '.modernjs/ultramodern.json');
15
13
  const defaultOut = path.join(
16
14
  workspaceRoot,
17
15
  '.codex/reports/cloudflare-version-proof/public-url-proof.json',
@@ -21,6 +19,276 @@ function readJson(filePath) {
21
19
  return JSON.parse(fs.readFileSync(filePath, 'utf8'));
22
20
  }
23
21
 
22
+ function toKebabCase(value) {
23
+ return String(value)
24
+ .trim()
25
+ .replace(/([a-z0-9])([A-Z])/gu, '$1-$2')
26
+ .replace(/[^a-zA-Z0-9._-]+/gu, '-')
27
+ .replace(/[._]+/gu, '-')
28
+ .toLowerCase()
29
+ .replace(/-+/gu, '-')
30
+ .replace(/^-+|-+$/gu, '');
31
+ }
32
+
33
+ function toPascalCase(value) {
34
+ return toKebabCase(value)
35
+ .split('-')
36
+ .filter(Boolean)
37
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
38
+ .join('');
39
+ }
40
+
41
+ function toEnvSegment(value) {
42
+ return toKebabCase(value).replace(/-/gu, '_').toUpperCase();
43
+ }
44
+
45
+ function normalizeRelativePath(value) {
46
+ return String(value ?? '').replace(/\\/gu, '/').replace(/^\.\/+/u, '');
47
+ }
48
+
49
+ function appNamespace(app) {
50
+ return app.kind === 'shell' ? 'shell' : (app.domain ?? app.id);
51
+ }
52
+
53
+ function normalizeCompactApp(rawApp) {
54
+ const id = String(rawApp.id);
55
+ const kind = rawApp.kind === 'vertical' ? 'vertical' : 'shell';
56
+ const appPath =
57
+ typeof rawApp.path === 'string'
58
+ ? normalizeRelativePath(rawApp.path)
59
+ : kind === 'shell'
60
+ ? 'apps/shell-super-app'
61
+ : `verticals/${toKebabCase(id)}`;
62
+ const packageSuffix =
63
+ typeof rawApp.packageSuffix === 'string'
64
+ ? rawApp.packageSuffix
65
+ : appPath.split('/').at(-1) ?? id;
66
+ const domain =
67
+ typeof rawApp.domain === 'string'
68
+ ? rawApp.domain
69
+ : kind === 'vertical'
70
+ ? packageSuffix
71
+ : undefined;
72
+ const moduleFederation =
73
+ rawApp.moduleFederation && typeof rawApp.moduleFederation === 'object'
74
+ ? rawApp.moduleFederation
75
+ : {};
76
+ const api =
77
+ rawApp.api && typeof rawApp.api === 'object'
78
+ ? {
79
+ stem:
80
+ typeof rawApp.api.stem === 'string'
81
+ ? rawApp.api.stem
82
+ : domain ?? id,
83
+ prefix:
84
+ typeof rawApp.api.prefix === 'string'
85
+ ? rawApp.api.prefix
86
+ : `/${domain ?? id}-api`,
87
+ }
88
+ : undefined;
89
+
90
+ return {
91
+ id,
92
+ kind,
93
+ path: appPath,
94
+ packageSuffix,
95
+ domain,
96
+ mfName:
97
+ typeof moduleFederation.name === 'string'
98
+ ? moduleFederation.name
99
+ : kind === 'shell'
100
+ ? 'shellSuperApp'
101
+ : `vertical${toPascalCase(domain ?? id)}`,
102
+ api,
103
+ };
104
+ }
105
+
106
+ function createBuildMarker(scope, app) {
107
+ return crypto
108
+ .createHash('sha256')
109
+ .update(`${scope}:${app.packageSuffix}:${app.id}:0.1.0`)
110
+ .digest('hex')
111
+ .slice(0, 16);
112
+ }
113
+
114
+ function createCloudflareSecurity() {
115
+ return {
116
+ enabled: true,
117
+ headers: {
118
+ referrerPolicy: 'strict-origin-when-cross-origin',
119
+ contentTypeOptions: 'nosniff',
120
+ permissionsPolicy:
121
+ 'camera=(), geolocation=(), microphone=(), payment=(), usb=()',
122
+ },
123
+ contentSecurityPolicy: {
124
+ mode: 'report-only',
125
+ directives: {
126
+ 'base-uri': [`'self'`],
127
+ 'connect-src': [`'self'`, 'https:', 'http:', 'wss:', 'ws:'],
128
+ 'default-src': [`'self'`],
129
+ 'font-src': [`'self'`, 'data:', 'https:', 'http:'],
130
+ 'form-action': [`'self'`],
131
+ 'frame-ancestors': [`'self'`],
132
+ 'img-src': [`'self'`, 'data:', 'blob:', 'https:', 'http:'],
133
+ 'manifest-src': [`'self'`, 'https:', 'http:'],
134
+ 'object-src': [`'none'`],
135
+ 'script-src': [
136
+ `'self'`,
137
+ `'unsafe-inline'`,
138
+ `'unsafe-eval'`,
139
+ 'https:',
140
+ 'http:',
141
+ 'blob:',
142
+ ],
143
+ 'style-src': [`'self'`, `'unsafe-inline'`, 'https:', 'http:'],
144
+ 'worker-src': [`'self'`, 'blob:'],
145
+ },
146
+ reason:
147
+ 'Report-only by default so Cloudflare Module Federation SSR can prove remote script, style, and connect compatibility before enforcement.',
148
+ },
149
+ noindex: {
150
+ workersDev: true,
151
+ localhost: true,
152
+ previewHostnames: [],
153
+ },
154
+ };
155
+ }
156
+
157
+ function createQualityGates() {
158
+ return {
159
+ publicRoutes: {
160
+ requireSitemapWhenPresent: true,
161
+ requireRobotsSitemapConsistency: true,
162
+ requireWebManifestWhenPresent: true,
163
+ },
164
+ statusCodes: {
165
+ notFoundRoute: '/__ultramodern-smoke-missing/nope',
166
+ unknownRouteStatus: 404,
167
+ },
168
+ indexing: {
169
+ previewNoindex: true,
170
+ productionPublicRoutesIndexable: true,
171
+ },
172
+ assets: {
173
+ cssPreloadRequired: true,
174
+ cssResponseRequired: true,
175
+ cacheControlRequiredForCss: true,
176
+ sourcemapsPubliclyReferenced: false,
177
+ },
178
+ budgets: {
179
+ ssrHtmlMaxBytes: 250_000,
180
+ mfManifestMaxBytes: 500_000,
181
+ localeJsonMaxBytes: 100_000,
182
+ sitemapXmlMaxBytes: 500_000,
183
+ cssAssetMaxBytes: 750_000,
184
+ },
185
+ csp: {
186
+ finalMode: 'report-only-dogfood',
187
+ decision:
188
+ 'Report-only remains the generated final mode until public smoke proof records MF SSR script/style/connect compatibility for the deployed surface.',
189
+ },
190
+ };
191
+ }
192
+
193
+ function createPublicHead() {
194
+ return {
195
+ alternates: {
196
+ hreflang: ['en', 'cs'],
197
+ xDefault: 'en',
198
+ },
199
+ };
200
+ }
201
+
202
+ function createPublicSurface() {
203
+ return {
204
+ publicRoutes: [],
205
+ routeEntries: [],
206
+ contentSources: [],
207
+ concreteUrlPaths: [],
208
+ };
209
+ }
210
+
211
+ function createCloudflareRoutes(app) {
212
+ return {
213
+ ssr: '/en',
214
+ mfManifest: '/mf-manifest.json',
215
+ locale: `/locales/en/${appNamespace(app)}.json`,
216
+ ...(app.api
217
+ ? {
218
+ apiReadiness: `${app.api.prefix}/${app.api.stem}/readiness`,
219
+ }
220
+ : {}),
221
+ };
222
+ }
223
+
224
+ function createContractApp(config, app) {
225
+ const packageScope =
226
+ typeof config.workspace?.packageScope === 'string'
227
+ ? config.workspace.packageScope
228
+ : path.basename(workspaceRoot);
229
+ const compatibilityDate =
230
+ typeof config.deploy?.worker?.compatibilityDate === 'string'
231
+ ? config.deploy.worker.compatibilityDate
232
+ : '2026-06-02';
233
+
234
+ return {
235
+ id: app.id,
236
+ deploy: {
237
+ cloudflare: {
238
+ workerName: `${toKebabCase(packageScope)}-${app.packageSuffix}`.slice(
239
+ 0,
240
+ 63,
241
+ ),
242
+ publicUrlEnv: `ULTRAMODERN_PUBLIC_URL_${toEnvSegment(app.id)}`,
243
+ compatibilityDate,
244
+ compatibilityFlags: ['nodejs_compat', 'global_fetch_strictly_public'],
245
+ routes: createCloudflareRoutes(app),
246
+ security: createCloudflareSecurity(),
247
+ qualityGates: createQualityGates(),
248
+ },
249
+ },
250
+ i18n: {
251
+ namespace: appNamespace(app),
252
+ },
253
+ marker: {
254
+ appId: app.id,
255
+ build: createBuildMarker(packageScope, app),
256
+ },
257
+ routes: {
258
+ publicHead: createPublicHead(),
259
+ publicSurface: createPublicSurface(),
260
+ },
261
+ styling: {
262
+ federation: {
263
+ rootSelector: `[data-app-id="${app.id}"]`,
264
+ },
265
+ },
266
+ };
267
+ }
268
+
269
+ function synthesizeContractFromCompactConfig(config) {
270
+ const apps = Array.isArray(config.topology?.apps)
271
+ ? config.topology.apps.map(normalizeCompactApp)
272
+ : [];
273
+
274
+ return {
275
+ sourcePath: compactConfigPath,
276
+ apps: apps.map(app => createContractApp(config, app)),
277
+ };
278
+ }
279
+
280
+ function readGeneratedContractView() {
281
+ if (fs.existsSync(compactConfigPath)) {
282
+ return synthesizeContractFromCompactConfig(readJson(compactConfigPath));
283
+ }
284
+ throw new Error(
285
+ `Missing UltraModern config. Expected ${path.relative(
286
+ workspaceRoot,
287
+ compactConfigPath,
288
+ )}.`,
289
+ );
290
+ }
291
+
24
292
  function parseArgs(argv) {
25
293
  const parsed = {
26
294
  appId: undefined,
@@ -50,7 +318,7 @@ function parseArgs(argv) {
50
318
 
51
319
  function printHelp() {
52
320
  process.stdout.write(`Usage:
53
- node scripts/proof-cloudflare-version.mjs [--app workspace] [--out evidence.json] [--require-public-urls]
321
+ node scripts/proof-cloudflare-version.mts [--app workspace] [--out evidence.json] [--require-public-urls]
54
322
 
55
323
  Set each app's public URL using the contract env key, for example:
56
324
  ULTRAMODERN_PUBLIC_URL_WORKSPACE=https://workspace.example.workers.dev
@@ -70,7 +338,7 @@ async function main(argv = process.argv.slice(2)) {
70
338
  return 0;
71
339
  }
72
340
 
73
- const contract = readJson(contractPath);
341
+ const contract = readGeneratedContractView();
74
342
  const apps = args.appId
75
343
  ? contract.apps.filter(app => app.id === args.appId)
76
344
  : contract.apps;
@@ -101,7 +369,7 @@ async function main(argv = process.argv.slice(2)) {
101
369
  schemaVersion: 1,
102
370
  generatedAt: new Date().toISOString(),
103
371
  status: results.length > 0 ? 'pass' : 'skipped',
104
- contractPath,
372
+ contractPath: contract.sourcePath ?? compactConfigPath,
105
373
  results,
106
374
  skipped,
107
375
  };
@@ -6,6 +6,20 @@ function normalizeUrlWithTrailingSlash(url) {
6
6
  return url.endsWith('/') ? url : `${url}/`;
7
7
  }
8
8
 
9
+ function resolveModuleFederationPublicPath(publicPath, manifestUrl) {
10
+ if (typeof publicPath !== 'string' || publicPath.trim().length === 0) {
11
+ return undefined;
12
+ }
13
+
14
+ try {
15
+ return normalizeUrlWithTrailingSlash(
16
+ new URL(publicPath.trim(), manifestUrl).toString(),
17
+ );
18
+ } catch {
19
+ return undefined;
20
+ }
21
+ }
22
+
9
23
  async function fetchText(url) {
10
24
  const response = await fetch(url);
11
25
  return {
@@ -464,7 +478,8 @@ async function validateSsrHead(evidence, app, publicUrl, ssrRoute, ssr) {
464
478
  async function validateNotFound(evidence, app, publicUrl) {
465
479
  const qualityGates = app.deploy?.cloudflare?.qualityGates ?? {};
466
480
  const notFoundRoute =
467
- qualityGates.statusCodes?.notFoundRoute ?? '/__ultramodern-smoke-missing';
481
+ qualityGates.statusCodes?.notFoundRoute ??
482
+ '/__ultramodern-smoke-missing/nope';
468
483
  const expectedStatus = qualityGates.statusCodes?.unknownRouteStatus ?? 404;
469
484
  const response = await fetchText(joinUrl(publicUrl, notFoundRoute));
470
485
  evidence.assertions.push({
@@ -721,7 +736,8 @@ async function validateModuleFederationManifestEvidence(evidence, app, publicUrl
721
736
  const budgets = qualityGates.budgets ?? {};
722
737
 
723
738
  const manifestRoute = routes.mfManifest ?? '/mf-manifest.json';
724
- const manifest = await fetchText(joinUrl(publicUrl, manifestRoute));
739
+ const manifestUrl = joinUrl(publicUrl, manifestRoute);
740
+ const manifest = await fetchText(manifestUrl);
725
741
  const manifestJson = parseMaybeJson(manifest.body);
726
742
  evidence.assertions.push({
727
743
  type: 'mf-manifest',
@@ -754,17 +770,26 @@ async function validateModuleFederationManifestEvidence(evidence, app, publicUrl
754
770
  manifest.accessControlAllowOrigin === '*',
755
771
  `${app.id} MF manifest is missing Cloudflare CORS headers`,
756
772
  );
757
- const expectedPublicPath = normalizeUrlWithTrailingSlash(publicUrl);
773
+ const expectedPublicPath = normalizeUrlWithTrailingSlash(
774
+ new URL('.', manifestUrl).toString(),
775
+ );
758
776
  const manifestPublicPath = manifestJson?.metaData?.publicPath;
777
+ const resolvedPublicPath = resolveModuleFederationPublicPath(
778
+ manifestPublicPath,
779
+ manifestUrl,
780
+ );
759
781
  evidence.assertions.push({
760
782
  type: 'mf-manifest-public-path',
761
783
  expected: expectedPublicPath,
762
784
  actual: manifestPublicPath,
763
- status: manifestPublicPath === expectedPublicPath ? 'pass' : 'fail',
785
+ resolved: resolvedPublicPath,
786
+ status: resolvedPublicPath === expectedPublicPath ? 'pass' : 'fail',
764
787
  });
765
788
  assert(
766
- manifestPublicPath === expectedPublicPath,
767
- `${app.id} MF manifest publicPath must resolve remote assets from ${expectedPublicPath}`,
789
+ resolvedPublicPath === expectedPublicPath,
790
+ `${app.id} MF manifest publicPath must resolve remote assets from ${expectedPublicPath}; got ${String(
791
+ manifestPublicPath,
792
+ )}`,
768
793
  );
769
794
  }
770
795
 
@@ -815,13 +840,13 @@ async function validateI18nEvidence(evidence, app, publicUrl, routes) {
815
840
  }
816
841
 
817
842
  async function validateReadinessEvidence(evidence, app, publicUrl, routes) {
818
- if (routes.effectReadiness) {
819
- const readiness = await fetchText(joinUrl(publicUrl, routes.effectReadiness));
843
+ if (routes.apiReadiness) {
844
+ const readiness = await fetchText(joinUrl(publicUrl, routes.apiReadiness));
820
845
  const readinessJson = parseMaybeJson(readiness.body);
821
846
  const apiMarker = markerFromJson(readinessJson);
822
847
  evidence.assertions.push({
823
848
  type: 'api-marker',
824
- route: routes.effectReadiness,
849
+ route: routes.apiReadiness,
825
850
  expected: app.marker?.build,
826
851
  actual: apiMarker,
827
852
  status: readiness.ok && apiMarker === app.marker?.build ? 'pass' : 'fail',
@@ -848,4 +873,4 @@ async function validateApp(app, publicUrl) {
848
873
  return evidence;
849
874
  }
850
875
 
851
- export { validateApp };
876
+ export { resolveModuleFederationPublicPath, validateApp };