@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.
- package/README.md +25 -23
- package/dist/cjs/index.cjs +37 -4
- package/dist/cjs/locale/en.cjs +12 -2
- package/dist/cjs/locale/zh.cjs +12 -2
- package/dist/cjs/ultramodern-tooling/commands.cjs +185 -0
- package/dist/cjs/ultramodern-tooling/config.cjs +172 -0
- package/dist/cjs/ultramodern-workspace/add-vertical.cjs +87 -75
- package/dist/cjs/ultramodern-workspace/{effect-api.cjs → api.cjs} +207 -208
- package/dist/cjs/ultramodern-workspace/bridge-config.cjs +327 -0
- package/dist/cjs/ultramodern-workspace/codesmith.cjs +1 -0
- package/dist/cjs/ultramodern-workspace/contracts.cjs +127 -657
- package/dist/cjs/ultramodern-workspace/demo-components.cjs +12 -12
- package/dist/cjs/ultramodern-workspace/descriptors.cjs +25 -25
- package/dist/cjs/ultramodern-workspace/fs-io.cjs +117 -0
- package/dist/cjs/ultramodern-workspace/generation-result.cjs +5 -5
- package/dist/cjs/ultramodern-workspace/index.cjs +4 -0
- package/dist/cjs/ultramodern-workspace/mf-validation.cjs +571 -0
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +33 -18
- package/dist/cjs/ultramodern-workspace/overlays.cjs +2 -2
- package/dist/cjs/ultramodern-workspace/package-json.cjs +57 -41
- package/dist/cjs/ultramodern-workspace/policy.cjs +4 -4
- package/dist/cjs/ultramodern-workspace/public-api.cjs +4 -0
- package/dist/cjs/ultramodern-workspace/public-surface.cjs +2 -2
- package/dist/cjs/ultramodern-workspace/versions.cjs +5 -0
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +119 -50
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +62 -21
- package/dist/esm/index.js +37 -4
- package/dist/esm/locale/en.js +12 -2
- package/dist/esm/locale/zh.js +12 -2
- package/dist/esm/ultramodern-tooling/commands.js +132 -0
- package/dist/esm/ultramodern-tooling/config.js +120 -0
- package/dist/esm/ultramodern-workspace/add-vertical.js +88 -79
- package/dist/esm/ultramodern-workspace/{effect-api.js → api.js} +146 -147
- package/dist/esm/ultramodern-workspace/bridge-config.js +270 -0
- package/dist/esm/ultramodern-workspace/codesmith.js +1 -0
- package/dist/esm/ultramodern-workspace/contracts.js +129 -611
- package/dist/esm/ultramodern-workspace/demo-components.js +13 -13
- package/dist/esm/ultramodern-workspace/descriptors.js +11 -11
- package/dist/esm/ultramodern-workspace/fs-io.js +116 -2
- package/dist/esm/ultramodern-workspace/generation-result.js +6 -6
- package/dist/esm/ultramodern-workspace/index.js +1 -0
- package/dist/esm/ultramodern-workspace/mf-validation.js +516 -0
- package/dist/esm/ultramodern-workspace/module-federation.js +34 -19
- package/dist/esm/ultramodern-workspace/overlays.js +2 -2
- package/dist/esm/ultramodern-workspace/package-json.js +56 -40
- package/dist/esm/ultramodern-workspace/policy.js +5 -5
- package/dist/esm/ultramodern-workspace/public-api.js +1 -0
- package/dist/esm/ultramodern-workspace/public-surface.js +2 -2
- package/dist/esm/ultramodern-workspace/versions.js +3 -1
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +107 -34
- package/dist/esm/ultramodern-workspace/write-workspace.js +64 -26
- package/dist/esm-node/index.js +37 -4
- package/dist/esm-node/locale/en.js +12 -2
- package/dist/esm-node/locale/zh.js +12 -2
- package/dist/esm-node/ultramodern-tooling/commands.js +133 -0
- package/dist/esm-node/ultramodern-tooling/config.js +121 -0
- package/dist/esm-node/ultramodern-workspace/add-vertical.js +88 -79
- package/dist/esm-node/ultramodern-workspace/{effect-api.js → api.js} +146 -147
- package/dist/esm-node/ultramodern-workspace/bridge-config.js +271 -0
- package/dist/esm-node/ultramodern-workspace/codesmith.js +1 -0
- package/dist/esm-node/ultramodern-workspace/contracts.js +129 -611
- package/dist/esm-node/ultramodern-workspace/demo-components.js +13 -13
- package/dist/esm-node/ultramodern-workspace/descriptors.js +11 -11
- package/dist/esm-node/ultramodern-workspace/fs-io.js +116 -2
- package/dist/esm-node/ultramodern-workspace/generation-result.js +6 -6
- package/dist/esm-node/ultramodern-workspace/index.js +1 -0
- package/dist/esm-node/ultramodern-workspace/mf-validation.js +517 -0
- package/dist/esm-node/ultramodern-workspace/module-federation.js +34 -19
- package/dist/esm-node/ultramodern-workspace/overlays.js +2 -2
- package/dist/esm-node/ultramodern-workspace/package-json.js +56 -40
- package/dist/esm-node/ultramodern-workspace/policy.js +5 -5
- package/dist/esm-node/ultramodern-workspace/public-api.js +1 -0
- package/dist/esm-node/ultramodern-workspace/public-surface.js +2 -2
- package/dist/esm-node/ultramodern-workspace/versions.js +3 -1
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +107 -34
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +64 -26
- package/dist/types/locale/en.d.ts +10 -0
- package/dist/types/locale/index.d.ts +20 -0
- package/dist/types/locale/zh.d.ts +10 -0
- package/dist/types/ultramodern-tooling/commands.d.ts +1 -0
- package/dist/types/ultramodern-tooling/config.d.ts +43 -0
- package/dist/types/ultramodern-workspace/add-vertical.d.ts +5 -2
- package/dist/types/ultramodern-workspace/api.d.ts +73 -0
- package/dist/types/ultramodern-workspace/bridge-config.d.ts +64 -0
- package/dist/types/ultramodern-workspace/codesmith.d.ts +1 -0
- package/dist/types/ultramodern-workspace/contracts.d.ts +2 -17
- package/dist/types/ultramodern-workspace/descriptors.d.ts +10 -10
- package/dist/types/ultramodern-workspace/fs-io.d.ts +1 -0
- package/dist/types/ultramodern-workspace/index.d.ts +2 -0
- package/dist/types/ultramodern-workspace/mf-validation.d.ts +27 -0
- package/dist/types/ultramodern-workspace/package-json.d.ts +5 -4
- package/dist/types/ultramodern-workspace/public-api.d.ts +2 -0
- package/dist/types/ultramodern-workspace/types.d.ts +9 -7
- package/dist/types/ultramodern-workspace/versions.d.ts +2 -0
- package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +2 -7
- package/dist/types/ultramodern-workspace/write-workspace.d.ts +4 -2
- package/package.json +5 -3
- package/template-workspace/{.agents → .codex}/skills-lock.json +12 -12
- package/template-workspace/.github/workflows/ultramodern-workspace-gates.yml.handlebars +2 -0
- package/template-workspace/.gitignore.handlebars +3 -0
- package/template-workspace/AGENTS.md.handlebars +11 -5
- package/template-workspace/README.md.handlebars +15 -12
- package/template-workspace/oxfmt.config.ts +1 -0
- package/template-workspace/oxlint.config.ts +1 -0
- package/template-workspace/patches/@tanstack__router-core@1.171.13.patch +51 -0
- package/template-workspace/pnpm-workspace.yaml.handlebars +4 -0
- package/template-workspace/scripts/bootstrap-agent-skills.mjs +77 -67
- package/templates/workspace-scripts/assert-mf-types.mjs.handlebars +51 -8
- package/templates/workspace-scripts/check-ultramodern-api-boundaries.mts +344 -0
- package/templates/workspace-scripts/{check-ultramodern-i18n-boundaries.mjs → check-ultramodern-i18n-boundaries.mts} +1 -1
- package/templates/workspace-scripts/generate-public-surface-assets.mjs +246 -9
- package/templates/workspace-scripts/proof-cloudflare-version.mjs +277 -9
- package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +35 -10
- package/templates/workspace-scripts/ultramodern-performance-readiness.mjs +165 -2
- package/templates/workspace-scripts/ultramodern-typecheck.mjs +4 -2
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +840 -84
- package/dist/types/ultramodern-workspace/effect-api.d.ts +0 -73
- /package/template-workspace/{.agents → .codex}/rstackjs-agent-skills-LICENSE +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rsbuild-best-practices/SKILL.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/SKILL.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/command-map.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/common-analysis-patterns.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-common.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-rspack.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-webpack.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/rsdoctor-data-types.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rslib-best-practices/SKILL.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rslib-modern-package/SKILL.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rspack-best-practices/SKILL.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/SKILL.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/bottlenecks.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/tracing-guide.md +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/scripts/analyze_trace.js +0 -0
- /package/template-workspace/{.agents → .codex}/skills/rstest-best-practices/SKILL.md +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
2
3
|
import fs from 'node:fs';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
|
|
@@ -14,6 +15,21 @@ const expectedCloudflareBuildScript = {{expectedCloudflareBuildScriptJson}};
|
|
|
14
15
|
const expectedCloudflareDeployScript = {{expectedCloudflareDeployScriptJson}};
|
|
15
16
|
const expectedCloudflareSecurity = {{expectedCloudflareSecurityJson}};
|
|
16
17
|
const publicSurfaceManagedSourceAssetPaths = {{publicSurfaceManagedSourceAssetPathsJson}};
|
|
18
|
+
const compactConfigPath = '.modernjs/ultramodern.json';
|
|
19
|
+
const retiredMetadataPaths = [
|
|
20
|
+
'.modernjs/ultramodern-generated-contract.json',
|
|
21
|
+
'.modernjs/ultramodern-package-source.json',
|
|
22
|
+
'.modernjs/ultramodern-workspace-template-manifest.json',
|
|
23
|
+
];
|
|
24
|
+
const modernPackageCohort = [
|
|
25
|
+
'@modern-js/create',
|
|
26
|
+
'@modern-js/code-tools',
|
|
27
|
+
'@modern-js/app-tools',
|
|
28
|
+
'@modern-js/plugin-bff',
|
|
29
|
+
'@modern-js/plugin-i18n',
|
|
30
|
+
'@modern-js/plugin-tanstack',
|
|
31
|
+
'@modern-js/runtime',
|
|
32
|
+
];
|
|
17
33
|
const expectedModernPackageSpecifier = packageName => {
|
|
18
34
|
if (packageSource.strategy === 'workspace') {
|
|
19
35
|
return 'workspace:*';
|
|
@@ -70,6 +86,688 @@ const assertArray = (value, contract, fixArea) => {
|
|
|
70
86
|
};
|
|
71
87
|
const findById = (entries, id) =>
|
|
72
88
|
Array.isArray(entries) ? entries.find(entry => entry?.id === id) : undefined;
|
|
89
|
+
const generatedContractLabel = compactConfigPath;
|
|
90
|
+
const toKebabCase = value =>
|
|
91
|
+
String(value)
|
|
92
|
+
.trim()
|
|
93
|
+
.replace(/([a-z0-9])([A-Z])/gu, '$1-$2')
|
|
94
|
+
.replace(/[^a-zA-Z0-9._-]+/gu, '-')
|
|
95
|
+
.replace(/[._]+/gu, '-')
|
|
96
|
+
.toLowerCase()
|
|
97
|
+
.replace(/-+/gu, '-')
|
|
98
|
+
.replace(/^-+|-+$/gu, '');
|
|
99
|
+
const toPascalCase = value =>
|
|
100
|
+
toKebabCase(value)
|
|
101
|
+
.split('-')
|
|
102
|
+
.filter(Boolean)
|
|
103
|
+
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
|
|
104
|
+
.join('');
|
|
105
|
+
const toCamelCase = value => {
|
|
106
|
+
const pascal = toPascalCase(value);
|
|
107
|
+
return `${pascal.charAt(0).toLowerCase()}${pascal.slice(1)}`;
|
|
108
|
+
};
|
|
109
|
+
const toEnvSegment = value => toKebabCase(value).replace(/-/gu, '_').toUpperCase();
|
|
110
|
+
const packageNameFor = (scope, suffix) => `@${scope}/${suffix}`;
|
|
111
|
+
const normalizeRelativePath = value =>
|
|
112
|
+
String(value ?? '').replace(/\\/gu, '/').replace(/^\.\/+/u, '');
|
|
113
|
+
const appNamespace = app => (app.kind === 'shell' ? 'shell' : (app.domain ?? app.id));
|
|
114
|
+
const tailwindPrefixDigitWords = [
|
|
115
|
+
'zero',
|
|
116
|
+
'one',
|
|
117
|
+
'two',
|
|
118
|
+
'three',
|
|
119
|
+
'four',
|
|
120
|
+
'five',
|
|
121
|
+
'six',
|
|
122
|
+
'seven',
|
|
123
|
+
'eight',
|
|
124
|
+
'nine',
|
|
125
|
+
];
|
|
126
|
+
const tailwindPrefixFor = app =>
|
|
127
|
+
app.kind === 'shell'
|
|
128
|
+
? 'shell'
|
|
129
|
+
: String(app.domain ?? app.id)
|
|
130
|
+
.toLowerCase()
|
|
131
|
+
.replace(/[^a-z0-9]/gu, '')
|
|
132
|
+
.replace(/[0-9]/gu, digit => tailwindPrefixDigitWords[Number(digit)]);
|
|
133
|
+
const buildMarkerFor = app =>
|
|
134
|
+
crypto
|
|
135
|
+
.createHash('sha256')
|
|
136
|
+
.update(`${packageScope}:${app.packageSuffix}:${app.id}:0.1.0`)
|
|
137
|
+
.digest('hex')
|
|
138
|
+
.slice(0, 16);
|
|
139
|
+
const normalizeCompactApp = rawApp => {
|
|
140
|
+
const id = String(rawApp.id);
|
|
141
|
+
const kind = rawApp.kind === 'vertical' ? 'vertical' : 'shell';
|
|
142
|
+
const appPath =
|
|
143
|
+
typeof rawApp.path === 'string'
|
|
144
|
+
? normalizeRelativePath(rawApp.path)
|
|
145
|
+
: kind === 'shell'
|
|
146
|
+
? 'apps/shell-super-app'
|
|
147
|
+
: `verticals/${toKebabCase(id)}`;
|
|
148
|
+
const packageSuffix =
|
|
149
|
+
typeof rawApp.packageSuffix === 'string'
|
|
150
|
+
? rawApp.packageSuffix
|
|
151
|
+
: appPath.split('/').at(-1) ?? id;
|
|
152
|
+
const domain =
|
|
153
|
+
typeof rawApp.domain === 'string'
|
|
154
|
+
? rawApp.domain
|
|
155
|
+
: kind === 'vertical'
|
|
156
|
+
? packageSuffix
|
|
157
|
+
: undefined;
|
|
158
|
+
const moduleFederation =
|
|
159
|
+
rawApp.moduleFederation && typeof rawApp.moduleFederation === 'object'
|
|
160
|
+
? rawApp.moduleFederation
|
|
161
|
+
: {};
|
|
162
|
+
const api =
|
|
163
|
+
rawApp.api && typeof rawApp.api === 'object'
|
|
164
|
+
? {
|
|
165
|
+
stem:
|
|
166
|
+
typeof rawApp.api.stem === 'string'
|
|
167
|
+
? rawApp.api.stem
|
|
168
|
+
: domain ?? id,
|
|
169
|
+
prefix:
|
|
170
|
+
typeof rawApp.api.prefix === 'string'
|
|
171
|
+
? rawApp.api.prefix
|
|
172
|
+
: `/${domain ?? id}-api`,
|
|
173
|
+
consumedBy: Array.isArray(rawApp.api.consumedBy)
|
|
174
|
+
? rawApp.api.consumedBy.filter(
|
|
175
|
+
consumer => typeof consumer === 'string',
|
|
176
|
+
)
|
|
177
|
+
: ['shell-super-app', id],
|
|
178
|
+
}
|
|
179
|
+
: undefined;
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
id,
|
|
183
|
+
kind,
|
|
184
|
+
path: appPath,
|
|
185
|
+
package: typeof rawApp.package === 'string' ? rawApp.package : undefined,
|
|
186
|
+
packageSuffix,
|
|
187
|
+
domain,
|
|
188
|
+
port:
|
|
189
|
+
typeof rawApp.port === 'number'
|
|
190
|
+
? rawApp.port
|
|
191
|
+
: kind === 'shell'
|
|
192
|
+
? 3020
|
|
193
|
+
: 3030,
|
|
194
|
+
portEnv:
|
|
195
|
+
typeof rawApp.portEnv === 'string'
|
|
196
|
+
? rawApp.portEnv
|
|
197
|
+
: kind === 'shell'
|
|
198
|
+
? 'SHELL_SUPER_APP_PORT'
|
|
199
|
+
: `VERTICAL_${toEnvSegment(domain ?? id)}_PORT`,
|
|
200
|
+
mfName:
|
|
201
|
+
typeof moduleFederation.name === 'string'
|
|
202
|
+
? moduleFederation.name
|
|
203
|
+
: kind === 'shell'
|
|
204
|
+
? 'shellSuperApp'
|
|
205
|
+
: `vertical${toPascalCase(domain ?? id)}`,
|
|
206
|
+
exposes: Array.isArray(moduleFederation.exposes)
|
|
207
|
+
? moduleFederation.exposes.filter(expose => typeof expose === 'string')
|
|
208
|
+
: [],
|
|
209
|
+
moduleFederationSsr: moduleFederation.ssr !== false,
|
|
210
|
+
verticalRefs: Array.isArray(moduleFederation.verticalRefs)
|
|
211
|
+
? moduleFederation.verticalRefs.filter(ref => typeof ref === 'string')
|
|
212
|
+
: [],
|
|
213
|
+
api,
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
const compactAppsFromConfig = config =>
|
|
217
|
+
Array.isArray(config.topology?.apps)
|
|
218
|
+
? config.topology.apps.map(normalizeCompactApp)
|
|
219
|
+
: [];
|
|
220
|
+
const remoteDependencyAliasFor = app => toCamelCase(app.domain ?? app.id.replace(/^remote-/u, ''));
|
|
221
|
+
const remoteContractsFor = (app, apps) =>
|
|
222
|
+
(app.verticalRefs ?? [])
|
|
223
|
+
.map(ref => apps.find(candidate => candidate.id === ref))
|
|
224
|
+
.filter(Boolean)
|
|
225
|
+
.map(remote => ({
|
|
226
|
+
id: remote.id,
|
|
227
|
+
alias: remoteDependencyAliasFor(remote),
|
|
228
|
+
name: remote.mfName,
|
|
229
|
+
manifestEnv: `VERTICAL_${toEnvSegment(remote.domain ?? remote.id)}_MF_MANIFEST`,
|
|
230
|
+
manifestUrl: `http://localhost:${remote.port}/mf-manifest.json`,
|
|
231
|
+
}));
|
|
232
|
+
const createRouteOwnedEntries = app => {
|
|
233
|
+
const namespace = appNamespace(app);
|
|
234
|
+
const base = {
|
|
235
|
+
descriptionKey: `${namespace}.seo.description`,
|
|
236
|
+
mfBoundaryId: app.mfName,
|
|
237
|
+
namespace,
|
|
238
|
+
ownerAppId: app.id,
|
|
239
|
+
public: false,
|
|
240
|
+
indexable: false,
|
|
241
|
+
publicSurface: 'private-app-screen',
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
return [
|
|
245
|
+
{
|
|
246
|
+
...base,
|
|
247
|
+
canonicalPath: '/',
|
|
248
|
+
id: app.kind === 'shell' ? 'shell-home' : `${app.id}-home`,
|
|
249
|
+
localisedPaths: {
|
|
250
|
+
cs: '/',
|
|
251
|
+
en: '/',
|
|
252
|
+
},
|
|
253
|
+
titleKey: app.kind === 'shell' ? 'shell.title' : `${namespace}.title`,
|
|
254
|
+
},
|
|
255
|
+
];
|
|
256
|
+
};
|
|
257
|
+
const createPublicRoutes = app =>
|
|
258
|
+
createRouteOwnedEntries(app)
|
|
259
|
+
.filter(route => route.public && route.indexable)
|
|
260
|
+
.map(route => ({
|
|
261
|
+
canonicalPath: route.canonicalPath,
|
|
262
|
+
id: route.id,
|
|
263
|
+
localisedPaths: route.localisedPaths,
|
|
264
|
+
namespace: route.namespace,
|
|
265
|
+
ownerAppId: route.ownerAppId,
|
|
266
|
+
descriptionKey: route.descriptionKey,
|
|
267
|
+
titleKey: route.titleKey,
|
|
268
|
+
}));
|
|
269
|
+
const createLocalisedUrls = app =>
|
|
270
|
+
Object.fromEntries(
|
|
271
|
+
createRouteOwnedEntries(app).flatMap(route => {
|
|
272
|
+
if (route.canonicalPath === '/') {
|
|
273
|
+
return [];
|
|
274
|
+
}
|
|
275
|
+
return Array.from(
|
|
276
|
+
new Set([route.canonicalPath, ...Object.values(route.localisedPaths)]),
|
|
277
|
+
).map(pathname => [pathname, route.localisedPaths]);
|
|
278
|
+
}),
|
|
279
|
+
);
|
|
280
|
+
const createPublicSurface = app => {
|
|
281
|
+
const publicRoutes = createPublicRoutes(app);
|
|
282
|
+
return {
|
|
283
|
+
authoring: 'colocated-route-meta',
|
|
284
|
+
artifactLifecycle: 'build-and-deploy-output',
|
|
285
|
+
generatedManifest: './src/routes/ultramodern-route-metadata',
|
|
286
|
+
source: 'route-owned-public-routes',
|
|
287
|
+
metadataExport: './src/routes/ultramodern-route-metadata',
|
|
288
|
+
generator: 'scripts/generate-public-surface-assets.mts',
|
|
289
|
+
outputRoot: 'dist/public',
|
|
290
|
+
cloudflareOutputRoot: '.output/public',
|
|
291
|
+
privateRoutePolicy: 'omit-from-generated-public-surface',
|
|
292
|
+
files:
|
|
293
|
+
publicRoutes.length > 0
|
|
294
|
+
? ['robots.txt', 'sitemap.xml', 'site.webmanifest']
|
|
295
|
+
: ['robots.txt'],
|
|
296
|
+
omittedByDefault: ['api-catalog.json', 'llms.txt', 'security.txt'],
|
|
297
|
+
languages: ['en', 'cs'],
|
|
298
|
+
contentExpansion: {
|
|
299
|
+
authoring: 'route-owned-esm-provider',
|
|
300
|
+
defaultProviderFile: 'route.sitemap.mjs',
|
|
301
|
+
entryExport: 'default-or-entries',
|
|
302
|
+
paramsSource: 'params-or-localeParams',
|
|
303
|
+
draftPolicy: 'omit-draft-by-default',
|
|
304
|
+
indexablePolicy: 'omit-indexable-false',
|
|
305
|
+
lifecycle: 'executed-during-public-surface-generation',
|
|
306
|
+
},
|
|
307
|
+
contentSources: [],
|
|
308
|
+
publicRoutes,
|
|
309
|
+
routeEntries: [],
|
|
310
|
+
concreteUrlPaths: [],
|
|
311
|
+
};
|
|
312
|
+
};
|
|
313
|
+
const createPublicHead = () => ({
|
|
314
|
+
authoring: 'colocated-route-meta',
|
|
315
|
+
generator: './src/routes/ultramodern-route-head',
|
|
316
|
+
renderer: '@modern-js/runtime/head Helmet',
|
|
317
|
+
ssr: true,
|
|
318
|
+
title: {
|
|
319
|
+
required: true,
|
|
320
|
+
source: 'route.titleKey',
|
|
321
|
+
},
|
|
322
|
+
description: {
|
|
323
|
+
required: true,
|
|
324
|
+
source: 'route.descriptionKey',
|
|
325
|
+
},
|
|
326
|
+
canonical: {
|
|
327
|
+
publicIndexableOnly: true,
|
|
328
|
+
source: 'localized canonical route URL',
|
|
329
|
+
},
|
|
330
|
+
alternates: {
|
|
331
|
+
hreflang: ['en', 'cs'],
|
|
332
|
+
xDefault: 'en',
|
|
333
|
+
},
|
|
334
|
+
openGraph: {
|
|
335
|
+
publicIndexableOnly: true,
|
|
336
|
+
required: ['og:title', 'og:description', 'og:url', 'og:type'],
|
|
337
|
+
},
|
|
338
|
+
twitter: {
|
|
339
|
+
publicIndexableOnly: true,
|
|
340
|
+
required: ['twitter:card', 'twitter:title', 'twitter:description'],
|
|
341
|
+
},
|
|
342
|
+
structuredData: {
|
|
343
|
+
publicIndexableOnly: true,
|
|
344
|
+
optional: true,
|
|
345
|
+
source: 'route.jsonLd',
|
|
346
|
+
inference: false,
|
|
347
|
+
helperModule: './src/routes/ultramodern-jsonld',
|
|
348
|
+
helperTypes: [
|
|
349
|
+
'WebPage',
|
|
350
|
+
'WebApplication',
|
|
351
|
+
'SoftwareApplication',
|
|
352
|
+
'BreadcrumbList',
|
|
353
|
+
'FAQPage',
|
|
354
|
+
'Organization',
|
|
355
|
+
],
|
|
356
|
+
sanitizesHtmlOpenBracket: true,
|
|
357
|
+
},
|
|
358
|
+
privateRouteRobots: 'noindex, nofollow',
|
|
359
|
+
});
|
|
360
|
+
const createQualityGates = () => ({
|
|
361
|
+
publicRoutes: {
|
|
362
|
+
requireSitemapWhenPresent: true,
|
|
363
|
+
requireRobotsSitemapConsistency: true,
|
|
364
|
+
requireWebManifestWhenPresent: true,
|
|
365
|
+
},
|
|
366
|
+
statusCodes: {
|
|
367
|
+
notFoundRoute: '/__ultramodern-smoke-missing/nope',
|
|
368
|
+
unknownRouteStatus: 404,
|
|
369
|
+
},
|
|
370
|
+
indexing: {
|
|
371
|
+
previewNoindex: true,
|
|
372
|
+
productionPublicRoutesIndexable: true,
|
|
373
|
+
},
|
|
374
|
+
assets: {
|
|
375
|
+
cssPreloadRequired: true,
|
|
376
|
+
cssResponseRequired: true,
|
|
377
|
+
cacheControlRequiredForCss: true,
|
|
378
|
+
sourcemapsPubliclyReferenced: false,
|
|
379
|
+
},
|
|
380
|
+
budgets: {
|
|
381
|
+
ssrHtmlMaxBytes: 250_000,
|
|
382
|
+
mfManifestMaxBytes: 500_000,
|
|
383
|
+
localeJsonMaxBytes: 100_000,
|
|
384
|
+
sitemapXmlMaxBytes: 500_000,
|
|
385
|
+
cssAssetMaxBytes: 750_000,
|
|
386
|
+
},
|
|
387
|
+
csp: {
|
|
388
|
+
finalMode: 'report-only-dogfood',
|
|
389
|
+
decision:
|
|
390
|
+
'Report-only remains the generated final mode until public smoke proof records MF SSR script/style/connect compatibility for the deployed surface.',
|
|
391
|
+
},
|
|
392
|
+
});
|
|
393
|
+
const createCloudflareRoutes = app => ({
|
|
394
|
+
ssr: '/en',
|
|
395
|
+
mfManifest: '/mf-manifest.json',
|
|
396
|
+
locale: `/locales/en/${appNamespace(app)}.json`,
|
|
397
|
+
...(app.api
|
|
398
|
+
? {
|
|
399
|
+
apiReadiness: `${app.api.prefix}/${app.api.stem}/readiness`,
|
|
400
|
+
}
|
|
401
|
+
: {}),
|
|
402
|
+
});
|
|
403
|
+
const createCloudflareDeploy = app => ({
|
|
404
|
+
target: 'cloudflare',
|
|
405
|
+
workerName: expectedWorkerName(app.packageSuffix),
|
|
406
|
+
publicUrlEnv: `ULTRAMODERN_PUBLIC_URL_${toEnvSegment(app.id)}`,
|
|
407
|
+
compatibilityDate: '{{cloudflareCompatibilityDate}}',
|
|
408
|
+
compatibilityFlags: ['nodejs_compat', 'global_fetch_strictly_public'],
|
|
409
|
+
assetsBinding: 'ASSETS',
|
|
410
|
+
routes: createCloudflareRoutes(app),
|
|
411
|
+
security: expectedCloudflareSecurity,
|
|
412
|
+
qualityGates: createQualityGates(),
|
|
413
|
+
evidence: {
|
|
414
|
+
proofScript: 'scripts/proof-cloudflare-version.mts',
|
|
415
|
+
reportDefault:
|
|
416
|
+
'.codex/reports/cloudflare-version-proof/public-url-proof.json',
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
const createEffectReadiness = app => ({
|
|
420
|
+
endpoint: `/${app.api.stem}/readiness`,
|
|
421
|
+
marker: {
|
|
422
|
+
ui: 'ultramodernUiMarker',
|
|
423
|
+
api: 'ultramodernApiMarker',
|
|
424
|
+
skew: 'none',
|
|
425
|
+
},
|
|
426
|
+
checks: ['moduleFederation', 'ssr', 'translations', 'api'],
|
|
427
|
+
});
|
|
428
|
+
const createEffectRequestContext = () => ({
|
|
429
|
+
propagatedHeaders: [
|
|
430
|
+
'accept-language',
|
|
431
|
+
'authorization',
|
|
432
|
+
'traceparent',
|
|
433
|
+
'x-correlation-id',
|
|
434
|
+
'x-tenant-id',
|
|
435
|
+
'x-ultramodern-env',
|
|
436
|
+
'x-vertical-version-id',
|
|
437
|
+
],
|
|
438
|
+
source: 'shell-to-vertical-api-client',
|
|
439
|
+
});
|
|
440
|
+
const createEffectDomainOperations = app => {
|
|
441
|
+
const stem = app.api.stem;
|
|
442
|
+
const group = toCamelCase(stem);
|
|
443
|
+
const basePath = `/${stem}`;
|
|
444
|
+
return {
|
|
445
|
+
workspaceFeed: {
|
|
446
|
+
client: `list${toPascalCase(stem)}`,
|
|
447
|
+
method: 'GET',
|
|
448
|
+
path: basePath,
|
|
449
|
+
resource: 'workspace-items',
|
|
450
|
+
owner: app.id,
|
|
451
|
+
},
|
|
452
|
+
workspaceDetail: {
|
|
453
|
+
client: `get${toPascalCase(stem)}`,
|
|
454
|
+
method: 'GET',
|
|
455
|
+
path: `${basePath}/:id`,
|
|
456
|
+
resource: 'workspace-item',
|
|
457
|
+
owner: app.id,
|
|
458
|
+
},
|
|
459
|
+
workspaceCreate: {
|
|
460
|
+
client: `create${toPascalCase(stem)}`,
|
|
461
|
+
method: 'POST',
|
|
462
|
+
path: basePath,
|
|
463
|
+
resource: group,
|
|
464
|
+
owner: app.id,
|
|
465
|
+
},
|
|
466
|
+
};
|
|
467
|
+
};
|
|
468
|
+
const createEffectOperationContract = app => ({
|
|
469
|
+
group: toCamelCase(app.api.stem),
|
|
470
|
+
operations: {
|
|
471
|
+
readiness: {
|
|
472
|
+
method: 'GET',
|
|
473
|
+
path: `/${app.api.stem}/readiness`,
|
|
474
|
+
source: 'generated-client',
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
});
|
|
478
|
+
const createAppConfigContract = app => ({
|
|
479
|
+
preset: 'presetUltramodern',
|
|
480
|
+
plugins: [
|
|
481
|
+
'appTools',
|
|
482
|
+
'tanstackRouterPlugin',
|
|
483
|
+
'i18nPlugin',
|
|
484
|
+
...(app.api ? ['bffPlugin'] : []),
|
|
485
|
+
'moduleFederationPlugin',
|
|
486
|
+
'zephyrRspackPlugin',
|
|
487
|
+
],
|
|
488
|
+
dev: {
|
|
489
|
+
assetPrefix: '/',
|
|
490
|
+
},
|
|
491
|
+
output: {
|
|
492
|
+
assetPrefix: {
|
|
493
|
+
envFallbackOrder: ['MODERN_ASSET_PREFIX', 'ULTRAMODERN_ASSET_PREFIX'],
|
|
494
|
+
default: app.kind === 'shell' ? '/' : 'app-public-origin',
|
|
495
|
+
},
|
|
496
|
+
disableTsChecker: false,
|
|
497
|
+
},
|
|
498
|
+
performance: {
|
|
499
|
+
readinessDiagnostics: {
|
|
500
|
+
default: 'enabled',
|
|
501
|
+
optOut: {
|
|
502
|
+
env: 'ULTRAMODERN_PERFORMANCE_READINESS_DIAGNOSTICS=false',
|
|
503
|
+
config: 'scripts/ultramodern-performance-readiness.config.mjs',
|
|
504
|
+
},
|
|
505
|
+
failOn: 'framework-invariant',
|
|
506
|
+
},
|
|
507
|
+
},
|
|
508
|
+
rspack: {
|
|
509
|
+
output: {
|
|
510
|
+
uniqueName: app.mfName,
|
|
511
|
+
chunkLoadingGlobal: expectedChunkLoadingGlobal(app.mfName),
|
|
512
|
+
},
|
|
513
|
+
},
|
|
514
|
+
source: {
|
|
515
|
+
siteUrl: {
|
|
516
|
+
envFallbackOrder: [
|
|
517
|
+
'MODERN_PUBLIC_SITE_URL',
|
|
518
|
+
`ULTRAMODERN_PUBLIC_URL_${toEnvSegment(app.id)}`,
|
|
519
|
+
'ULTRAMODERN_CLOUDFLARE_WORKERS_DEV_SUBDOMAIN',
|
|
520
|
+
app.portEnv,
|
|
521
|
+
],
|
|
522
|
+
defaultLocalhostPort: app.port,
|
|
523
|
+
},
|
|
524
|
+
},
|
|
525
|
+
});
|
|
526
|
+
const cssDedupe = () => ({
|
|
527
|
+
strategy: 'shared-token-package-plus-css-content-hash',
|
|
528
|
+
sharedPackage: packageNameFor(packageScope, 'shared-design-tokens'),
|
|
529
|
+
sharedLayers: ['ultramodern-shared-tokens'],
|
|
530
|
+
runtimeLoad: 'once-per-content-hash',
|
|
531
|
+
duplicateBaseStylesAllowed: false,
|
|
532
|
+
});
|
|
533
|
+
const createStylingContract = app => {
|
|
534
|
+
const sharedTokenPackage = packageNameFor(packageScope, 'shared-design-tokens');
|
|
535
|
+
const ownedLayers =
|
|
536
|
+
app.kind === 'shell'
|
|
537
|
+
? ['ultramodern-shell-base', 'ultramodern-shell-overlay']
|
|
538
|
+
: [`ultramodern-vertical-${app.domain ?? app.id}`];
|
|
539
|
+
|
|
540
|
+
return {
|
|
541
|
+
tailwind: tailwindEnabled,
|
|
542
|
+
federation: {
|
|
543
|
+
owner: {
|
|
544
|
+
id: app.id,
|
|
545
|
+
package: app.package ?? packageNameFor(packageScope, app.packageSuffix),
|
|
546
|
+
},
|
|
547
|
+
role: app.kind === 'shell' ? 'shell-base-overlay' : 'vertical-css',
|
|
548
|
+
rootSelector: `[data-app-id="${app.id}"]`,
|
|
549
|
+
classPrefix: `${tailwindPrefixFor(app)}:`,
|
|
550
|
+
layers: {
|
|
551
|
+
shared: ['ultramodern-shared-tokens'],
|
|
552
|
+
owned: ownedLayers,
|
|
553
|
+
},
|
|
554
|
+
entrypoints: {
|
|
555
|
+
layoutImport: 'src/routes/layout.tsx',
|
|
556
|
+
css: ['src/routes/index.css'],
|
|
557
|
+
...(app.kind === 'shell'
|
|
558
|
+
? {}
|
|
559
|
+
: { federationEntry: 'src/federation-entry.tsx' }),
|
|
560
|
+
},
|
|
561
|
+
assets: {
|
|
562
|
+
shared: [`${sharedTokenPackage}/tokens.css`],
|
|
563
|
+
owned: ['src/routes/index.css'],
|
|
564
|
+
},
|
|
565
|
+
dedupe: cssDedupe(),
|
|
566
|
+
ssr: {
|
|
567
|
+
cloudflare: true,
|
|
568
|
+
firstPaintRequired: true,
|
|
569
|
+
verticalCss:
|
|
570
|
+
app.kind === 'shell'
|
|
571
|
+
? 'host-preloads-shell-and-shared-css'
|
|
572
|
+
: 'federated-manifest-owned-css',
|
|
573
|
+
},
|
|
574
|
+
},
|
|
575
|
+
};
|
|
576
|
+
};
|
|
577
|
+
const createAppContract = (app, apps) => ({
|
|
578
|
+
id: app.id,
|
|
579
|
+
package: app.package ?? packageNameFor(packageScope, app.packageSuffix),
|
|
580
|
+
path: app.path,
|
|
581
|
+
kind: app.kind,
|
|
582
|
+
config: createAppConfigContract(app),
|
|
583
|
+
styling: createStylingContract(app),
|
|
584
|
+
deploy: {
|
|
585
|
+
target: 'cloudflare',
|
|
586
|
+
cloudflare: createCloudflareDeploy(app),
|
|
587
|
+
worker: {
|
|
588
|
+
compatibilityDate: '{{cloudflareCompatibilityDate}}',
|
|
589
|
+
name: expectedWorkerName(app.packageSuffix),
|
|
590
|
+
security: expectedCloudflareSecurity,
|
|
591
|
+
ssr: true,
|
|
592
|
+
},
|
|
593
|
+
},
|
|
594
|
+
ssr: app.moduleFederationSsr
|
|
595
|
+
? {
|
|
596
|
+
mode: 'string',
|
|
597
|
+
moduleFederationAppSSR: true,
|
|
598
|
+
}
|
|
599
|
+
: undefined,
|
|
600
|
+
i18n: {
|
|
601
|
+
languages: ['en', 'cs'],
|
|
602
|
+
namespace: appNamespace(app),
|
|
603
|
+
localisedUrls: createLocalisedUrls(app),
|
|
604
|
+
},
|
|
605
|
+
routes: {
|
|
606
|
+
source: 'route-owned',
|
|
607
|
+
metadataAuthoring: 'colocated-route-meta',
|
|
608
|
+
generatedManifest: true,
|
|
609
|
+
metadataExport: './src/routes/ultramodern-route-metadata',
|
|
610
|
+
localisedUrls: createLocalisedUrls(app),
|
|
611
|
+
owned: createRouteOwnedEntries(app),
|
|
612
|
+
publicRoutes: createPublicRoutes(app),
|
|
613
|
+
privateByDefault: true,
|
|
614
|
+
publicnessDefault: 'private-app-screen',
|
|
615
|
+
publicHead: createPublicHead(),
|
|
616
|
+
publicSurface: createPublicSurface(app),
|
|
617
|
+
},
|
|
618
|
+
moduleFederation: {
|
|
619
|
+
name: app.mfName,
|
|
620
|
+
...(app.verticalRefs?.length
|
|
621
|
+
? {
|
|
622
|
+
verticalRefs: app.verticalRefs,
|
|
623
|
+
remotes: remoteContractsFor(app, apps),
|
|
624
|
+
}
|
|
625
|
+
: {}),
|
|
626
|
+
exposes: app.exposes,
|
|
627
|
+
dts: {
|
|
628
|
+
compilerInstance: 'tsgo',
|
|
629
|
+
displayErrorInTerminal: true,
|
|
630
|
+
tsConfigPath: './tsconfig.mf-types.json',
|
|
631
|
+
},
|
|
632
|
+
browserSafeExposesOnly: true,
|
|
633
|
+
},
|
|
634
|
+
marker: {
|
|
635
|
+
appId: app.id,
|
|
636
|
+
packageName: app.package ?? packageNameFor(packageScope, app.packageSuffix),
|
|
637
|
+
version: '0.1.0',
|
|
638
|
+
build: buildMarkerFor(app),
|
|
639
|
+
deployProfile: 'cloudflare-ssr-mf-effect-v1',
|
|
640
|
+
uiSurface: 'ui',
|
|
641
|
+
...(app.api ? { apiSurface: 'api' } : {}),
|
|
642
|
+
},
|
|
643
|
+
...(app.api
|
|
644
|
+
? {
|
|
645
|
+
api: {
|
|
646
|
+
runtime: 'effect',
|
|
647
|
+
import: '@modern-js/plugin-bff/effect-edge',
|
|
648
|
+
prefix: app.api.prefix,
|
|
649
|
+
openapi: '/openapi.json',
|
|
650
|
+
strictEffectApproach: true,
|
|
651
|
+
workerEntry: 'worker/__modern_bff_effect.js',
|
|
652
|
+
contract: './api',
|
|
653
|
+
client: './api/client',
|
|
654
|
+
readiness: createEffectReadiness(app),
|
|
655
|
+
requestContext: createEffectRequestContext(),
|
|
656
|
+
domainOperations: createEffectDomainOperations(app),
|
|
657
|
+
...createEffectOperationContract(app),
|
|
658
|
+
},
|
|
659
|
+
}
|
|
660
|
+
: {}),
|
|
661
|
+
});
|
|
662
|
+
const createCssFederationContract = () => ({
|
|
663
|
+
sharedDesignTokens: {
|
|
664
|
+
owner: {
|
|
665
|
+
id: 'shared-design-tokens',
|
|
666
|
+
package: packageNameFor(packageScope, 'shared-design-tokens'),
|
|
667
|
+
},
|
|
668
|
+
role: 'shared-design-tokens',
|
|
669
|
+
rootSelector: ':root',
|
|
670
|
+
classPrefix: '--um-',
|
|
671
|
+
layers: {
|
|
672
|
+
owned: ['ultramodern-shared-tokens'],
|
|
673
|
+
},
|
|
674
|
+
entrypoints: {
|
|
675
|
+
css: ['packages/shared-design-tokens/src/tokens.css'],
|
|
676
|
+
},
|
|
677
|
+
assets: {
|
|
678
|
+
exports: ['./tokens.css'],
|
|
679
|
+
},
|
|
680
|
+
dedupe: cssDedupe(),
|
|
681
|
+
ssr: {
|
|
682
|
+
firstPaintRequired: true,
|
|
683
|
+
},
|
|
684
|
+
},
|
|
685
|
+
});
|
|
686
|
+
const createPerformanceReadinessContract = () => ({
|
|
687
|
+
default: 'enabled',
|
|
688
|
+
mode: 'diagnostic',
|
|
689
|
+
scope: 'ultramodern-generated-and-framework-owned',
|
|
690
|
+
report: {
|
|
691
|
+
script: 'scripts/ultramodern-performance-readiness.mts',
|
|
692
|
+
config: 'scripts/ultramodern-performance-readiness.config.mjs',
|
|
693
|
+
deterministic: true,
|
|
694
|
+
},
|
|
695
|
+
optOut: {
|
|
696
|
+
env: 'ULTRAMODERN_PERFORMANCE_READINESS_DIAGNOSTICS=false',
|
|
697
|
+
},
|
|
698
|
+
signals: [
|
|
699
|
+
'bfcache',
|
|
700
|
+
'core-web-vitals-rum',
|
|
701
|
+
'duplicate-prefetch-warmup',
|
|
702
|
+
'cache-policy-sanity',
|
|
703
|
+
'save-data-behavior',
|
|
704
|
+
'cloudflare-ssr-cache-hints',
|
|
705
|
+
].map(id => ({ id })),
|
|
706
|
+
});
|
|
707
|
+
const createModernPackageAliases = packageSourceConfig => {
|
|
708
|
+
if (typeof packageSourceConfig?.aliasScope !== 'string') {
|
|
709
|
+
return undefined;
|
|
710
|
+
}
|
|
711
|
+
const scope = packageSourceConfig.aliasScope.replace(/^@/u, '');
|
|
712
|
+
const prefix =
|
|
713
|
+
typeof packageSourceConfig.aliasPackageNamePrefix === 'string'
|
|
714
|
+
? packageSourceConfig.aliasPackageNamePrefix
|
|
715
|
+
: '';
|
|
716
|
+
return Object.fromEntries(
|
|
717
|
+
modernPackageCohort.map(packageName => [
|
|
718
|
+
packageName,
|
|
719
|
+
`@${scope}/${prefix}${packageName.split('/').at(-1)}`,
|
|
720
|
+
]),
|
|
721
|
+
);
|
|
722
|
+
};
|
|
723
|
+
const synthesizePackageSourceFromCompact = config => {
|
|
724
|
+
const source = config.packageSource ?? {};
|
|
725
|
+
const strategy = source.strategy === 'install' ? 'install' : 'workspace';
|
|
726
|
+
const specifier =
|
|
727
|
+
strategy === 'install' && typeof source.modernPackageVersion === 'string'
|
|
728
|
+
? source.modernPackageVersion
|
|
729
|
+
: 'workspace:*';
|
|
730
|
+
const aliases = createModernPackageAliases(source);
|
|
731
|
+
return {
|
|
732
|
+
schemaVersion: 1,
|
|
733
|
+
strategy,
|
|
734
|
+
modernPackages: {
|
|
735
|
+
packages: modernPackageCohort,
|
|
736
|
+
specifier,
|
|
737
|
+
...(typeof source.registry === 'string'
|
|
738
|
+
? { registry: source.registry }
|
|
739
|
+
: {}),
|
|
740
|
+
...(aliases ? { aliases } : {}),
|
|
741
|
+
},
|
|
742
|
+
generatedWorkspacePackages: {
|
|
743
|
+
packages: [
|
|
744
|
+
packageNameFor(packageScope, 'shared-contracts'),
|
|
745
|
+
packageNameFor(packageScope, 'shared-design-tokens'),
|
|
746
|
+
],
|
|
747
|
+
specifier: 'workspace:*',
|
|
748
|
+
},
|
|
749
|
+
};
|
|
750
|
+
};
|
|
751
|
+
const synthesizeGeneratedContractFromCompact = config => {
|
|
752
|
+
const apps = compactAppsFromConfig(config);
|
|
753
|
+
return {
|
|
754
|
+
schemaVersion: 1,
|
|
755
|
+
profile: config.profile ?? 'cloudflare-ssr-mf-effect-v1',
|
|
756
|
+
node: {
|
|
757
|
+
version: config.workspace?.node?.version ?? expectedNodeVersion,
|
|
758
|
+
engineRange: '>=26',
|
|
759
|
+
},
|
|
760
|
+
performanceReadiness: createPerformanceReadinessContract(),
|
|
761
|
+
cssFederation: createCssFederationContract(),
|
|
762
|
+
apps: apps.map(app => createAppContract(app, apps)),
|
|
763
|
+
};
|
|
764
|
+
};
|
|
765
|
+
const readPackageSourceView = config => {
|
|
766
|
+
return synthesizePackageSourceFromCompact(config);
|
|
767
|
+
};
|
|
768
|
+
const readGeneratedContractView = config => {
|
|
769
|
+
return synthesizeGeneratedContractFromCompact(config);
|
|
770
|
+
};
|
|
73
771
|
const expectedManifestUrl = vertical =>
|
|
74
772
|
`http://localhost:${vertical.port}/mf-manifest.json`;
|
|
75
773
|
const expectedApiUrl = vertical =>
|
|
@@ -95,9 +793,9 @@ const requiredMicroVerticalPaths = vertical => [
|
|
|
95
793
|
`${vertical.path}/tsconfig.mf-types.json`,
|
|
96
794
|
`${vertical.path}/modern.config.ts`,
|
|
97
795
|
`${vertical.path}/module-federation.config.ts`,
|
|
98
|
-
`${vertical.path}/api/
|
|
99
|
-
`${vertical.path}/shared/
|
|
100
|
-
`${vertical.path}/src/
|
|
796
|
+
`${vertical.path}/api/index.ts`,
|
|
797
|
+
`${vertical.path}/shared/api.ts`,
|
|
798
|
+
`${vertical.path}/src/api/${vertical.stem}-client.ts`,
|
|
101
799
|
`${vertical.path}/src/modern-app-env.d.ts`,
|
|
102
800
|
`${vertical.path}/src/modern.runtime.ts`,
|
|
103
801
|
`${vertical.path}/src/federation-entry.tsx`,
|
|
@@ -173,11 +871,11 @@ const assertMicroVerticalContractGraph = ({
|
|
|
173
871
|
assertObject(
|
|
174
872
|
overlay.apis,
|
|
175
873
|
'topology/local-overlays/development.json apis',
|
|
176
|
-
'restore generated local
|
|
874
|
+
'restore generated local API overlays',
|
|
177
875
|
);
|
|
178
876
|
assertArray(
|
|
179
877
|
generatedContract.apps,
|
|
180
|
-
|
|
878
|
+
`${generatedContractLabel} apps`,
|
|
181
879
|
'regenerate the generated contract from the workspace topology',
|
|
182
880
|
);
|
|
183
881
|
|
|
@@ -202,26 +900,26 @@ const assertMicroVerticalContractGraph = ({
|
|
|
202
900
|
assertSameJson(
|
|
203
901
|
generatedContract.apps.map(app => app?.id),
|
|
204
902
|
expectedAppIds,
|
|
205
|
-
|
|
903
|
+
`${generatedContractLabel} apps`,
|
|
206
904
|
'regenerate the generated contract after topology changes',
|
|
207
905
|
);
|
|
208
906
|
|
|
209
907
|
const shellContract = findById(generatedContract.apps, 'shell-super-app');
|
|
210
908
|
assertObject(
|
|
211
909
|
shellContract,
|
|
212
|
-
|
|
910
|
+
`${generatedContractLabel} apps.shell-super-app`,
|
|
213
911
|
'regenerate the generated shell contract entry',
|
|
214
912
|
);
|
|
215
913
|
assertSameJson(
|
|
216
914
|
shellContract.moduleFederation?.verticalRefs ?? [],
|
|
217
915
|
expectedVerticalIds,
|
|
218
|
-
|
|
916
|
+
`${generatedContractLabel} shell moduleFederation.verticalRefs`,
|
|
219
917
|
'regenerate the generated shell Module Federation contract',
|
|
220
918
|
);
|
|
221
919
|
assertSameJson(
|
|
222
920
|
(shellContract.moduleFederation?.remotes ?? []).map(remoteContractSubset),
|
|
223
921
|
expectedShellRemotes,
|
|
224
|
-
|
|
922
|
+
`${generatedContractLabel} shell moduleFederation.remotes`,
|
|
225
923
|
'regenerate the generated shell Module Federation contract',
|
|
226
924
|
);
|
|
227
925
|
assertSameJson(
|
|
@@ -230,7 +928,7 @@ const assertMicroVerticalContractGraph = ({
|
|
|
230
928
|
mode: 'string',
|
|
231
929
|
moduleFederationAppSSR: true,
|
|
232
930
|
},
|
|
233
|
-
|
|
931
|
+
`${generatedContractLabel} shell SSR contract`,
|
|
234
932
|
'restore generated string SSR Module Federation settings',
|
|
235
933
|
);
|
|
236
934
|
|
|
@@ -266,9 +964,9 @@ const assertMicroVerticalContractGraph = ({
|
|
|
266
964
|
remoteContractSubset,
|
|
267
965
|
),
|
|
268
966
|
},
|
|
269
|
-
|
|
270
|
-
prefix: topologyEntry.api?.
|
|
271
|
-
serverEntry: topologyEntry.api?.
|
|
967
|
+
api: {
|
|
968
|
+
prefix: topologyEntry.api?.bff?.prefix,
|
|
969
|
+
serverEntry: topologyEntry.api?.serverEntry,
|
|
272
970
|
},
|
|
273
971
|
},
|
|
274
972
|
{
|
|
@@ -282,9 +980,9 @@ const assertMicroVerticalContractGraph = ({
|
|
|
282
980
|
verticalRefs: expectedRefs,
|
|
283
981
|
remotes: expectedRemoteSubsetsForRefs(expectedRefs),
|
|
284
982
|
},
|
|
285
|
-
|
|
983
|
+
api: {
|
|
286
984
|
prefix: vertical.apiPrefix,
|
|
287
|
-
serverEntry: `${vertical.path}/api/
|
|
985
|
+
serverEntry: `${vertical.path}/api/index.ts`,
|
|
288
986
|
},
|
|
289
987
|
},
|
|
290
988
|
`topology/reference-topology.json verticals.${vertical.id}`,
|
|
@@ -325,14 +1023,14 @@ const assertMicroVerticalContractGraph = ({
|
|
|
325
1023
|
overlay.apis[vertical.id],
|
|
326
1024
|
expectedApiUrl(vertical),
|
|
327
1025
|
`topology/local-overlays/development.json apis.${vertical.id}`,
|
|
328
|
-
'restore generated local
|
|
1026
|
+
'restore generated local API overlay',
|
|
329
1027
|
);
|
|
330
1028
|
|
|
331
1029
|
assertSameJson(
|
|
332
1030
|
shellPackage.dependencies?.[vertical.packageName],
|
|
333
1031
|
'workspace:*',
|
|
334
1032
|
`apps/shell-super-app/package.json dependencies.${vertical.packageName}`,
|
|
335
|
-
'restore shell dependency for the MicroVertical
|
|
1033
|
+
'restore shell dependency for the MicroVertical API consumer',
|
|
336
1034
|
);
|
|
337
1035
|
assertSameJson(
|
|
338
1036
|
shellPackage['zephyr:dependencies']?.[vertical.zephyrAlias],
|
|
@@ -343,7 +1041,7 @@ const assertMicroVerticalContractGraph = ({
|
|
|
343
1041
|
|
|
344
1042
|
assertObject(
|
|
345
1043
|
contractEntry,
|
|
346
|
-
|
|
1044
|
+
`${generatedContractLabel} apps.${vertical.id}`,
|
|
347
1045
|
'regenerate the generated MicroVertical contract entry',
|
|
348
1046
|
);
|
|
349
1047
|
assertSameJson(
|
|
@@ -359,10 +1057,10 @@ const assertMicroVerticalContractGraph = ({
|
|
|
359
1057
|
remoteContractSubset,
|
|
360
1058
|
),
|
|
361
1059
|
},
|
|
362
|
-
|
|
363
|
-
prefix: contractEntry.
|
|
364
|
-
contract: contractEntry.
|
|
365
|
-
client: contractEntry.
|
|
1060
|
+
api: {
|
|
1061
|
+
prefix: contractEntry.api?.prefix,
|
|
1062
|
+
contract: contractEntry.api?.contract,
|
|
1063
|
+
client: contractEntry.api?.client,
|
|
366
1064
|
},
|
|
367
1065
|
ssr: contractEntry.ssr,
|
|
368
1066
|
},
|
|
@@ -376,17 +1074,17 @@ const assertMicroVerticalContractGraph = ({
|
|
|
376
1074
|
verticalRefs: expectedRefs,
|
|
377
1075
|
remotes: expectedRemoteSubsetsForRefs(expectedRefs),
|
|
378
1076
|
},
|
|
379
|
-
|
|
1077
|
+
api: {
|
|
380
1078
|
prefix: vertical.apiPrefix,
|
|
381
|
-
contract: './
|
|
382
|
-
client: './
|
|
1079
|
+
contract: './api',
|
|
1080
|
+
client: './api/client',
|
|
383
1081
|
},
|
|
384
1082
|
ssr: {
|
|
385
1083
|
mode: 'string',
|
|
386
1084
|
moduleFederationAppSSR: true,
|
|
387
1085
|
},
|
|
388
1086
|
},
|
|
389
|
-
|
|
1087
|
+
`${generatedContractLabel} apps.${vertical.id}`,
|
|
390
1088
|
'regenerate the generated MicroVertical contract entry',
|
|
391
1089
|
);
|
|
392
1090
|
}
|
|
@@ -586,7 +1284,7 @@ const assertPublicSurfaceAssets = (appPath, publicRoutes) => {
|
|
|
586
1284
|
};
|
|
587
1285
|
const assertPublicSurfaceContract = (appId, publicSurface) => {
|
|
588
1286
|
assert(publicSurface?.artifactLifecycle === 'build-and-deploy-output', `${appId} public surface artifacts must be build/deploy outputs`);
|
|
589
|
-
assert(publicSurface?.generator === 'scripts/generate-public-surface-assets.
|
|
1287
|
+
assert(publicSurface?.generator === 'scripts/generate-public-surface-assets.mts', `${appId} public surface generator script is incorrect`);
|
|
590
1288
|
assert(publicSurface?.outputRoot === 'dist/public', `${appId} public surface dist outputRoot is incorrect`);
|
|
591
1289
|
assert(publicSurface?.cloudflareOutputRoot === '.output/public', `${appId} public surface Cloudflare outputRoot is incorrect`);
|
|
592
1290
|
assert(!('staticRoot' in (publicSurface ?? {})), `${appId} public surface must not point at source config/public`);
|
|
@@ -770,24 +1468,23 @@ const requiredPaths = [
|
|
|
770
1468
|
'oxfmt.config.ts',
|
|
771
1469
|
'.github/renovate.json',
|
|
772
1470
|
'.github/workflows/ultramodern-workspace-gates.yml',
|
|
773
|
-
'.agents/skills-lock.json',
|
|
774
1471
|
'.agents/agent-reference-repos.json',
|
|
775
|
-
'.
|
|
1472
|
+
'.codex/skills-lock.json',
|
|
1473
|
+
'.codex/rstackjs-agent-skills-LICENSE',
|
|
776
1474
|
'topology/reference-topology.json',
|
|
777
1475
|
'topology/ownership.json',
|
|
778
1476
|
'topology/local-overlays/development.json',
|
|
779
|
-
'
|
|
780
|
-
'
|
|
781
|
-
'
|
|
782
|
-
'scripts/
|
|
783
|
-
'scripts/
|
|
784
|
-
'scripts/
|
|
785
|
-
'scripts/
|
|
786
|
-
'scripts/proof-cloudflare-version.mjs',
|
|
787
|
-
'scripts/setup-agent-reference-repos.mjs',
|
|
1477
|
+
'scripts/assert-mf-types.mts',
|
|
1478
|
+
'scripts/bootstrap-agent-skills.mts',
|
|
1479
|
+
'scripts/check-ultramodern-api-boundaries.mts',
|
|
1480
|
+
'scripts/check-ultramodern-i18n-boundaries.mts',
|
|
1481
|
+
'scripts/generate-public-surface-assets.mts',
|
|
1482
|
+
'scripts/proof-cloudflare-version.mts',
|
|
1483
|
+
'scripts/setup-agent-reference-repos.mts',
|
|
788
1484
|
'scripts/ultramodern-performance-readiness.config.mjs',
|
|
789
|
-
'scripts/ultramodern-performance-readiness.
|
|
790
|
-
'scripts/ultramodern-typecheck.
|
|
1485
|
+
'scripts/ultramodern-performance-readiness.mts',
|
|
1486
|
+
'scripts/ultramodern-typecheck.mts',
|
|
1487
|
+
'scripts/validate-ultramodern-workspace.mts',
|
|
791
1488
|
'apps/shell-super-app/package.json',
|
|
792
1489
|
'apps/shell-super-app/tsconfig.json',
|
|
793
1490
|
'apps/shell-super-app/tsconfig.mf-types.json',
|
|
@@ -795,7 +1492,7 @@ const requiredPaths = [
|
|
|
795
1492
|
'apps/shell-super-app/module-federation.config.ts',
|
|
796
1493
|
'apps/shell-super-app/src/modern-app-env.d.ts',
|
|
797
1494
|
'apps/shell-super-app/src/modern.runtime.ts',
|
|
798
|
-
'apps/shell-super-app/src/
|
|
1495
|
+
'apps/shell-super-app/src/api/vertical-clients.ts',
|
|
799
1496
|
'apps/shell-super-app/locales/en/translation.json',
|
|
800
1497
|
`apps/shell-super-app/locales/en/${shellNamespace}.json`,
|
|
801
1498
|
'apps/shell-super-app/locales/cs/translation.json',
|
|
@@ -830,6 +1527,8 @@ if (tailwindEnabled) {
|
|
|
830
1527
|
);
|
|
831
1528
|
}
|
|
832
1529
|
|
|
1530
|
+
requiredPaths.push(compactConfigPath);
|
|
1531
|
+
|
|
833
1532
|
for (const vertical of fullStackVerticals) {
|
|
834
1533
|
requiredMicroVerticalPaths(vertical).forEach(
|
|
835
1534
|
assertRequiredVerticalFile(vertical),
|
|
@@ -841,9 +1540,15 @@ for (const requiredPath of requiredPaths) {
|
|
|
841
1540
|
for (const oldRemotePath of oldRemotePaths) {
|
|
842
1541
|
assertNotExists(oldRemotePath);
|
|
843
1542
|
}
|
|
1543
|
+
for (const retiredMetadataPath of retiredMetadataPaths) {
|
|
1544
|
+
assertNotExists(retiredMetadataPath);
|
|
1545
|
+
}
|
|
844
1546
|
const rootPackage = readJson('package.json');
|
|
845
|
-
const
|
|
846
|
-
const
|
|
1547
|
+
const ultramodernConfig = readJson(compactConfigPath);
|
|
1548
|
+
const bridgeConfig =
|
|
1549
|
+
ultramodernConfig?.bridge?.enabled === true ? ultramodernConfig.bridge : undefined;
|
|
1550
|
+
const packageSource = readPackageSourceView(ultramodernConfig);
|
|
1551
|
+
const generatedContract = readGeneratedContractView(ultramodernConfig);
|
|
847
1552
|
const topology = readJson('topology/reference-topology.json');
|
|
848
1553
|
const ownership = readJson('topology/ownership.json');
|
|
849
1554
|
const overlay = readJson('topology/local-overlays/development.json');
|
|
@@ -882,7 +1587,10 @@ assert(
|
|
|
882
1587
|
);
|
|
883
1588
|
assert(!workflowText.includes('FORCE_JAVASCRIPT_ACTIONS_TO_NODE24'), 'CI workflow must not carry the legacy Node 24 override');
|
|
884
1589
|
assert(rootPackage.modernjs?.preset === 'presetUltramodern', 'Root must declare presetUltramodern');
|
|
885
|
-
assert(
|
|
1590
|
+
assert(
|
|
1591
|
+
rootPackage.modernjs?.packageSource?.config === './.modernjs/ultramodern.json',
|
|
1592
|
+
'Root must point at compact UltraModern config',
|
|
1593
|
+
);
|
|
886
1594
|
assert(rootPackage.modernjs?.packageSource?.strategy === packageSource.strategy, 'Root package source strategy must match metadata');
|
|
887
1595
|
assert(packageSource.strategy === 'workspace' || packageSource.strategy === 'install', 'Package source strategy must be workspace or install');
|
|
888
1596
|
assert(packageSource.strategy === 'install' || packageSource.modernPackages?.specifier === 'workspace:*', 'Workspace package source must be explicitly backed by workspace:*');
|
|
@@ -930,38 +1638,80 @@ assert(
|
|
|
930
1638
|
);
|
|
931
1639
|
assert(rootPackage.scripts?.['cloudflare:build'] === expectedCloudflareBuildScript, 'Root cloudflare:build script is incorrect');
|
|
932
1640
|
assert(!('ultramodern:check' in (rootPackage.scripts ?? {})), 'Root must not expose ultramodern:check');
|
|
933
|
-
|
|
934
|
-
assert(
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1641
|
+
if (bridgeConfig) {
|
|
1642
|
+
assert(
|
|
1643
|
+
rootPackage.scripts?.typecheck ===
|
|
1644
|
+
'pnpm -r --filter "./apps/*" --filter "./verticals/*" --filter "./packages/*" run typecheck',
|
|
1645
|
+
'Bridge root typecheck must check generated package boundaries without building parent implementation sources',
|
|
1646
|
+
);
|
|
1647
|
+
assert(Array.isArray(bridgeConfig.workspacePackages), 'Bridge config must record workspace package patterns');
|
|
1648
|
+
for (const workspacePackage of bridgeConfig.workspacePackages) {
|
|
1649
|
+
assert(
|
|
1650
|
+
rootPackage.workspaces?.includes(workspacePackage.pattern),
|
|
1651
|
+
`Root workspaces must include bridge package pattern ${workspacePackage.pattern}`,
|
|
1652
|
+
);
|
|
1653
|
+
assert(
|
|
1654
|
+
readText('pnpm-workspace.yaml').includes(` - ${workspacePackage.pattern}`),
|
|
1655
|
+
`pnpm-workspace.yaml must include bridge package pattern ${workspacePackage.pattern}`,
|
|
1656
|
+
);
|
|
1657
|
+
}
|
|
1658
|
+
for (const gate of bridgeConfig.gates ?? []) {
|
|
1659
|
+
const expectedGateScript = `${gate.cwd ? `cd ${gate.cwd} && ` : ''}${gate.command}`;
|
|
1660
|
+
assert(
|
|
1661
|
+
rootPackage.scripts?.[`bridge:${gate.name}`] === expectedGateScript,
|
|
1662
|
+
`Bridge gate script bridge:${gate.name} is incorrect`,
|
|
1663
|
+
);
|
|
1664
|
+
}
|
|
1665
|
+
assert(rootPackage.scripts?.['bridge:check'], 'Bridge workspaces must expose bridge:check');
|
|
1666
|
+
} else {
|
|
1667
|
+
assert(rootPackage.scripts?.typecheck === 'node ./scripts/ultramodern-typecheck.mts --build tsconfig.json', 'Root typecheck must run TS-Go build mode across project references');
|
|
1668
|
+
}
|
|
1669
|
+
assert(rootPackage.scripts?.['contract:check'] === 'node ./scripts/validate-ultramodern-workspace.mts', 'Root must expose contract:check');
|
|
1670
|
+
assert(rootPackage.scripts?.['api:check'] === 'node ./scripts/check-ultramodern-api-boundaries.mts', 'Root must expose api:check');
|
|
1671
|
+
assert(rootPackage.scripts?.['i18n:boundaries'] === 'node ./scripts/check-ultramodern-i18n-boundaries.mts', 'Root must expose i18n:boundaries');
|
|
1672
|
+
assert(rootPackage.scripts?.['performance:readiness'] === 'node ./scripts/ultramodern-performance-readiness.mts', 'Root must expose default-on performance readiness diagnostics');
|
|
1673
|
+
assert(
|
|
1674
|
+
bridgeConfig
|
|
1675
|
+
? rootPackage.scripts?.check?.includes('pnpm api:check') &&
|
|
1676
|
+
rootPackage.scripts.check.endsWith('&& pnpm performance:readiness && pnpm bridge:check')
|
|
1677
|
+
: rootPackage.scripts?.check?.includes('pnpm api:check') &&
|
|
1678
|
+
rootPackage.scripts.check.endsWith('&& pnpm performance:readiness'),
|
|
1679
|
+
'Root check must run default-on performance readiness diagnostics and bridge gates when configured',
|
|
1680
|
+
);
|
|
938
1681
|
const performanceReadinessConfig = readText('scripts/ultramodern-performance-readiness.config.mjs');
|
|
939
|
-
const
|
|
1682
|
+
const assertToolWrapper = (scriptPath, command) => {
|
|
1683
|
+
const source = readText(scriptPath);
|
|
1684
|
+
assert(source.includes('modern-js-create'), `${scriptPath} must delegate to modern-js-create`);
|
|
1685
|
+
assert(source.includes('ULTRAMODERN_CREATE_BIN'), `${scriptPath} must support local create-bin overrides for generated-workspace tests`);
|
|
1686
|
+
assert(source.includes("'ultramodern'") || source.includes('"ultramodern"'), `${scriptPath} must dispatch through the UltraModern tool surface`);
|
|
1687
|
+
assert(source.includes(command), `${scriptPath} must dispatch ${command}`);
|
|
1688
|
+
};
|
|
940
1689
|
assert(performanceReadinessConfig.includes('UltramodernPerformanceReadinessDiagnosticsConfig'), 'Performance readiness config must carry the typed opt-out surface');
|
|
941
1690
|
assert(performanceReadinessConfig.includes('enabled: true'), 'Performance readiness diagnostics must be default-on');
|
|
942
1691
|
assert(performanceReadinessConfig.includes("failOn: 'framework-invariant'"), 'Performance readiness diagnostics must only fail framework invariants by default');
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
const i18nBoundaryScript = readText('scripts/check-ultramodern-i18n-boundaries.
|
|
946
|
-
|
|
947
|
-
assert(ultramodernTypecheckScript.includes("'--checkers'") && ultramodernTypecheckScript.includes("'--builders'"), 'Root typecheck script must drive TS-Go checker and builder parallelism');
|
|
948
|
-
assert(ultramodernTypecheckScript.includes('effect-tsgo') && ultramodernTypecheckScript.includes('get-exe-path'), 'Root typecheck script must resolve the @effect/tsgo native-preview binary');
|
|
1692
|
+
assertToolWrapper('scripts/validate-ultramodern-workspace.mts', 'validate');
|
|
1693
|
+
assertToolWrapper('scripts/ultramodern-performance-readiness.mts', 'performance-readiness');
|
|
1694
|
+
const i18nBoundaryScript = readText('scripts/check-ultramodern-i18n-boundaries.mts');
|
|
1695
|
+
assertToolWrapper('scripts/ultramodern-typecheck.mts', 'typecheck');
|
|
949
1696
|
assert(
|
|
950
1697
|
i18nBoundaryScript.includes("from '@modern-js/code-tools'") &&
|
|
951
1698
|
i18nBoundaryScript.includes('runWorkspaceSourceCheck'),
|
|
952
1699
|
'Root i18n boundary script must call @modern-js/code-tools',
|
|
953
1700
|
);
|
|
954
|
-
assert(rootPackage.scripts?.['mf:types'] === 'node ./scripts/assert-mf-types.
|
|
1701
|
+
assert(rootPackage.scripts?.['mf:types'] === 'node ./scripts/assert-mf-types.mts', 'Root must expose mf:types');
|
|
955
1702
|
assert(rootPackage.scripts?.['cloudflare:deploy'] === expectedCloudflareDeployScript, 'Root must expose cloudflare:deploy');
|
|
956
|
-
assert(rootPackage.scripts?.['cloudflare:proof'] === 'node ./scripts/proof-cloudflare-version.
|
|
957
|
-
assert(rootPackage.scripts?.['skills:install'] === 'node ./scripts/bootstrap-agent-skills.
|
|
958
|
-
assert(rootPackage.scripts?.['skills:check'] === 'node ./scripts/bootstrap-agent-skills.
|
|
959
|
-
assert(rootPackage.scripts?.postinstall === "oxfmt . '!repos/**' && node ./scripts/bootstrap-agent-skills.
|
|
960
|
-
assert(rootPackage.scripts?.['agents:refs:install'] === 'node ./scripts/setup-agent-reference-repos.
|
|
961
|
-
const agentSkillsBootstrap = readText('scripts/bootstrap-agent-skills.
|
|
962
|
-
assert
|
|
1703
|
+
assert(rootPackage.scripts?.['cloudflare:proof'] === 'node ./scripts/proof-cloudflare-version.mts --out .codex/reports/cloudflare-version-proof/public-url-proof.json', 'Root must expose cloudflare:proof');
|
|
1704
|
+
assert(rootPackage.scripts?.['skills:install'] === 'node ./scripts/bootstrap-agent-skills.mts', 'Root must expose skills:install');
|
|
1705
|
+
assert(rootPackage.scripts?.['skills:check'] === 'node ./scripts/bootstrap-agent-skills.mts --check', 'Root must expose skills:check');
|
|
1706
|
+
assert(rootPackage.scripts?.postinstall === "oxfmt . '!repos/**' && node ./scripts/bootstrap-agent-skills.mts --postinstall", 'Root postinstall must format, run the default-on Codex skills bootstrap, and leave reference repository installs explicit');
|
|
1707
|
+
assert(rootPackage.scripts?.['agents:refs:install'] === 'node ./scripts/setup-agent-reference-repos.mts', 'Root must expose agents:refs:install as the explicit reference repo installer');
|
|
1708
|
+
const agentSkillsBootstrap = readText('scripts/bootstrap-agent-skills.mts');
|
|
1709
|
+
assertToolWrapper('scripts/assert-mf-types.mts', 'mf-types');
|
|
1710
|
+
assertToolWrapper('scripts/generate-public-surface-assets.mts', 'public-surface');
|
|
1711
|
+
assertToolWrapper('scripts/proof-cloudflare-version.mts', 'cloudflare-proof');
|
|
1712
|
+
assertToolWrapper('scripts/bootstrap-agent-skills.mts', 'skills');
|
|
963
1713
|
assert(!agentSkillsBootstrap.includes("run('brew'") && !agentSkillsBootstrap.includes('runShell('), 'Agent skills bootstrap must never invoke system package managers');
|
|
964
|
-
const agentReferenceRepoSetup = readText('scripts/setup-agent-reference-repos.
|
|
1714
|
+
const agentReferenceRepoSetup = readText('scripts/setup-agent-reference-repos.mts');
|
|
965
1715
|
assert(agentReferenceRepoSetup.includes("['commit', '--no-verify', '-m', message]"), 'Agent reference repo installer commits must skip hooks during postinstall');
|
|
966
1716
|
assert(agentReferenceRepoSetup.includes("commitInstallerChanges('Initialize UltraModern workspace')"), 'Initial agent reference repo commit must use the installer commit helper');
|
|
967
1717
|
assert(agentReferenceRepoSetup.includes("commitInstallerChanges('Record agent reference repo manifest')"), 'Agent reference repo manifest commit must use the installer commit helper');
|
|
@@ -992,7 +1742,7 @@ const expectedPerformanceReadinessSignals = [
|
|
|
992
1742
|
];
|
|
993
1743
|
assert(generatedContract.performanceReadiness?.default === 'enabled', 'Performance readiness diagnostics must be default-on in the generated contract');
|
|
994
1744
|
assert(generatedContract.performanceReadiness?.mode === 'diagnostic', 'Performance readiness must remain diagnostic-only');
|
|
995
|
-
assert(generatedContract.performanceReadiness?.report?.script === 'scripts/ultramodern-performance-readiness.
|
|
1745
|
+
assert(generatedContract.performanceReadiness?.report?.script === 'scripts/ultramodern-performance-readiness.mts', 'Performance readiness contract must point at the generated script');
|
|
996
1746
|
assert(generatedContract.performanceReadiness?.report?.deterministic === true, 'Performance readiness reports must be deterministic');
|
|
997
1747
|
assert(generatedContract.performanceReadiness?.optOut?.env === 'ULTRAMODERN_PERFORMANCE_READINESS_DIAGNOSTICS=false', 'Performance readiness env opt-out is incorrect');
|
|
998
1748
|
assert(JSON.stringify(generatedContract.performanceReadiness?.signals?.map(signal => signal.id)) === JSON.stringify(expectedPerformanceReadinessSignals), 'Performance readiness signal ids are incorrect');
|
|
@@ -1033,8 +1783,9 @@ assert(shellModernConfig.includes('name: cloudflareWorkerName'), 'Shell modern.c
|
|
|
1033
1783
|
assert(shellModernConfig.includes('const assetPrefix ='), 'Shell modern.config.ts must derive a dedicated asset prefix');
|
|
1034
1784
|
assert(shellModernConfig.includes("const configuredUltramodernAssetPrefix = envValue('ULTRAMODERN_ASSET_PREFIX')"), 'Shell asset prefix must support ULTRAMODERN_ASSET_PREFIX');
|
|
1035
1785
|
assert(shellModernConfig.includes("const configuredModernAssetPrefix = envValue('MODERN_ASSET_PREFIX')"), 'Shell asset prefix must support MODERN_ASSET_PREFIX');
|
|
1786
|
+
assert(shellModernConfig.includes("const defaultAssetPrefix = '/'"), 'Shell asset prefix must default to origin-relative assets');
|
|
1036
1787
|
const shellAssetPrefixExpression = extractAssetPrefixExpression(shellModernConfig);
|
|
1037
|
-
assert(shellAssetPrefixExpression.includes("configuredModernAssetPrefix || configuredUltramodernAssetPrefix ||
|
|
1788
|
+
assert(shellAssetPrefixExpression.includes("configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix"), 'Shell asset prefix fallback order is incorrect');
|
|
1038
1789
|
assert(!shellAssetPrefixExpression.includes('configuredSiteUrl') && !shellAssetPrefixExpression.includes('MODERN_PUBLIC_SITE_URL'), 'Shell asset prefix must not fall back to MODERN_PUBLIC_SITE_URL');
|
|
1039
1790
|
assert(!shellAssetPrefixExpression.includes('configuredCloudflareUrl') && !shellAssetPrefixExpression.includes('ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP'), 'Shell asset prefix must not fall back to the per-app public URL');
|
|
1040
1791
|
assert(!shellAssetPrefixExpression.includes('inferredCloudflareUrl') && !shellAssetPrefixExpression.includes('ULTRAMODERN_CLOUDFLARE_WORKERS_DEV_SUBDOMAIN'), 'Shell asset prefix must not infer workers.dev URLs');
|
|
@@ -1100,8 +1851,8 @@ for (const vertical of fullStackVerticals) {
|
|
|
1100
1851
|
assert(packageJson.dependencies?.['@modern-js/plugin-i18n'] === expectedModernPackageSpecifier('@modern-js/plugin-i18n'), `${vertical.id} plugin-i18n dependency must match package source metadata`);
|
|
1101
1852
|
assert(packageJson.dependencies?.['@modern-js/plugin-tanstack'] === expectedModernPackageSpecifier('@modern-js/plugin-tanstack'), `${vertical.id} plugin-tanstack dependency must match package source metadata`);
|
|
1102
1853
|
assert(packageJson.dependencies?.['@modern-js/runtime'] === expectedModernPackageSpecifier('@modern-js/runtime'), `${vertical.id} runtime dependency must match package source metadata`);
|
|
1103
|
-
assert(packageJson.exports?.['./
|
|
1104
|
-
assert(packageJson.exports?.['./
|
|
1854
|
+
assert(packageJson.exports?.['./api/client'] === `./src/api/${vertical.stem}-client.ts`, `${vertical.id} must export its API client`);
|
|
1855
|
+
assert(packageJson.exports?.['./api'] === './shared/api.ts', `${vertical.id} must export its API contract`);
|
|
1105
1856
|
const expectedVerticalZephyrDependencies = Object.fromEntries(
|
|
1106
1857
|
fullStackVerticals
|
|
1107
1858
|
.filter(candidate => vertical.verticalRefs.includes(candidate.id))
|
|
@@ -1132,21 +1883,23 @@ for (const vertical of fullStackVerticals) {
|
|
|
1132
1883
|
assert(modernConfig.includes('const assetPrefix ='), `${vertical.id} modern.config.ts must derive a dedicated asset prefix`);
|
|
1133
1884
|
assert(modernConfig.includes("const configuredUltramodernAssetPrefix = envValue('ULTRAMODERN_ASSET_PREFIX')"), `${vertical.id} asset prefix must support ULTRAMODERN_ASSET_PREFIX`);
|
|
1134
1885
|
assert(modernConfig.includes("const configuredModernAssetPrefix = envValue('MODERN_ASSET_PREFIX')"), `${vertical.id} asset prefix must support MODERN_ASSET_PREFIX`);
|
|
1886
|
+
assert(modernConfig.includes('const defaultRemoteAssetPrefix'), `${vertical.id} asset prefix must derive the remote asset origin`);
|
|
1887
|
+
assert(modernConfig.includes('const defaultAssetPrefix = defaultRemoteAssetPrefix'), `${vertical.id} asset prefix must default to its own remote origin`);
|
|
1135
1888
|
const verticalAssetPrefixExpression = extractAssetPrefixExpression(modernConfig);
|
|
1136
|
-
assert(verticalAssetPrefixExpression.includes("configuredModernAssetPrefix || configuredUltramodernAssetPrefix ||
|
|
1889
|
+
assert(verticalAssetPrefixExpression.includes("configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix"), `${vertical.id} asset prefix fallback order is incorrect`);
|
|
1137
1890
|
assert(!verticalAssetPrefixExpression.includes('configuredSiteUrl') && !verticalAssetPrefixExpression.includes('MODERN_PUBLIC_SITE_URL'), `${vertical.id} asset prefix must not fall back to MODERN_PUBLIC_SITE_URL`);
|
|
1138
|
-
assert(
|
|
1139
|
-
assert(
|
|
1891
|
+
assert(modernConfig.includes(`envValue('ULTRAMODERN_PUBLIC_URL_${vertical.id.replace(/-/g, '_').toUpperCase()}')`), `${vertical.id} asset prefix must read its per-app public URL`);
|
|
1892
|
+
assert(modernConfig.includes('inferredCloudflareUrl'), `${vertical.id} asset prefix must support workers.dev origin inference`);
|
|
1140
1893
|
assert(modernConfig.includes("assetPrefix: '/'"), `${vertical.id} modern.config.ts must keep dev assets origin-relative`);
|
|
1141
1894
|
assert(modernConfig.includes('assetPrefix,'), `${vertical.id} modern.config.ts must wire output.assetPrefix to the derived asset prefix`);
|
|
1142
1895
|
assert(contractEntry?.config?.dev?.assetPrefix === '/', `${vertical.id} dev asset prefix must stay origin-relative`);
|
|
1143
|
-
assert(contractEntry?.config?.output?.assetPrefix?.default === '
|
|
1896
|
+
assert(contractEntry?.config?.output?.assetPrefix?.default === 'app-public-origin', `${vertical.id} asset prefix must default to its app public origin`);
|
|
1144
1897
|
assert(JSON.stringify(contractEntry?.config?.output?.assetPrefix?.envFallbackOrder) === JSON.stringify(['MODERN_ASSET_PREFIX', 'ULTRAMODERN_ASSET_PREFIX']), `${vertical.id} asset prefix env fallback order is incorrect`);
|
|
1145
1898
|
assert(contractEntry?.config?.output?.disableTsChecker === false, `${vertical.id} must keep the framework TypeScript checker enabled`);
|
|
1146
1899
|
assert(contractEntry?.config?.performance?.readinessDiagnostics?.default === 'enabled', `${vertical.id} performance readiness diagnostics must be default-on`);
|
|
1147
1900
|
assert(contractEntry?.config?.performance?.readinessDiagnostics?.failOn === 'framework-invariant', `${vertical.id} performance readiness diagnostics must only fail framework invariants by default`);
|
|
1148
1901
|
assert(contractEntry?.config?.performance?.readinessDiagnostics?.optOut?.config === 'scripts/ultramodern-performance-readiness.config.mjs', `${vertical.id} performance readiness opt-out config is incorrect`);
|
|
1149
|
-
assert(contractEntry?.deploy?.cloudflare?.routes?.
|
|
1902
|
+
assert(contractEntry?.deploy?.cloudflare?.routes?.apiReadiness === `${vertical.apiPrefix}/${vertical.stem}/readiness`, `${vertical.id} Cloudflare proof readiness route is incorrect`);
|
|
1150
1903
|
assert(contractEntry?.config?.rspack?.output?.uniqueName === vertical.mfName, `${vertical.id} Rspack uniqueName is incorrect`);
|
|
1151
1904
|
assert(contractEntry?.config?.rspack?.output?.chunkLoadingGlobal === expectedChunkLoadingGlobal(vertical.mfName), `${vertical.id} Rspack chunkLoadingGlobal is incorrect`);
|
|
1152
1905
|
assert(contractEntry?.moduleFederation?.name === vertical.mfName, `${vertical.id} MF name is incorrect`);
|
|
@@ -1160,12 +1913,14 @@ for (const vertical of fullStackVerticals) {
|
|
|
1160
1913
|
JSON.stringify(vertical.verticalRefs),
|
|
1161
1914
|
`${vertical.id} MF consumed verticals are incorrect`,
|
|
1162
1915
|
);
|
|
1163
|
-
assert(contractEntry?.
|
|
1164
|
-
assert(contractEntry?.
|
|
1165
|
-
assert(contractEntry?.
|
|
1166
|
-
assert(contractEntry?.
|
|
1167
|
-
assert(contractEntry?.
|
|
1168
|
-
assert(
|
|
1916
|
+
assert(contractEntry?.api?.prefix === vertical.apiPrefix, `${vertical.id} API prefix is incorrect`);
|
|
1917
|
+
assert(contractEntry?.api?.group === vertical.group, `${vertical.id} API group is incorrect`);
|
|
1918
|
+
assert(contractEntry?.api?.runtime === 'effect', `${vertical.id} API runtime must be Effect`);
|
|
1919
|
+
assert(contractEntry?.api?.strictEffectApproach === true, `${vertical.id} strictEffectApproach must be enabled`);
|
|
1920
|
+
assert(contractEntry?.api?.readiness?.endpoint === `/${vertical.stem}/readiness`, `${vertical.id} readiness endpoint is incorrect`);
|
|
1921
|
+
assert(contractEntry?.api?.operations?.readiness?.path === `/${vertical.stem}/readiness`, `${vertical.id} readiness operation is missing`);
|
|
1922
|
+
assert(contractEntry?.api?.requestContext?.propagatedHeaders?.includes('traceparent'), `${vertical.id} trace context propagation is missing`);
|
|
1923
|
+
assert(Object.keys(contractEntry?.api?.domainOperations ?? {}).length >= 3, `${vertical.id} domain operations are missing`);
|
|
1169
1924
|
assert(contractEntry?.i18n?.languages?.includes('en') && contractEntry?.i18n?.languages?.includes('cs'), `${vertical.id} must declare i18n languages`);
|
|
1170
1925
|
assert(contractEntry?.i18n?.namespace === vertical.namespace, `${vertical.id} i18n namespace is incorrect`);
|
|
1171
1926
|
assert(
|
|
@@ -1204,10 +1959,11 @@ for (const vertical of fullStackVerticals) {
|
|
|
1204
1959
|
assert(topologyEntry?.moduleFederation?.name === vertical.mfName, `${vertical.id} topology MF name is incorrect`);
|
|
1205
1960
|
assert(JSON.stringify(topologyEntry?.moduleFederation?.exposes) === JSON.stringify(vertical.exposes), `${vertical.id} topology exposes are incorrect`);
|
|
1206
1961
|
assert(JSON.stringify(topologyEntry?.moduleFederation?.verticalRefs ?? []) === JSON.stringify(vertical.verticalRefs), `${vertical.id} topology verticalRefs are incorrect`);
|
|
1207
|
-
assert(topologyEntry?.api?.
|
|
1208
|
-
assert(topologyEntry?.api?.
|
|
1209
|
-
assert(topologyEntry?.api?.
|
|
1210
|
-
assert(
|
|
1962
|
+
assert(topologyEntry?.api?.bff?.prefix === vertical.apiPrefix, `${vertical.id} topology API prefix is incorrect`);
|
|
1963
|
+
assert(topologyEntry?.api?.bff?.strictEffectApproach === true, `${vertical.id} topology strictEffectApproach is incorrect`);
|
|
1964
|
+
assert(topologyEntry?.api?.serverEntry === `${vertical.path}/api/index.ts`, `${vertical.id} topology server entry is incorrect`);
|
|
1965
|
+
assert(topologyEntry?.api?.readiness?.endpoint === `/${vertical.stem}/readiness`, `${vertical.id} topology readiness endpoint is incorrect`);
|
|
1966
|
+
assert(Object.keys(topologyEntry?.api?.domainOperations ?? {}).length >= 3, `${vertical.id} topology domain operations are missing`);
|
|
1211
1967
|
|
|
1212
1968
|
assert(ownership.owners?.some(owner => owner.id === vertical.id && owner.path === vertical.path), `${vertical.id} ownership entry is missing`);
|
|
1213
1969
|
assert(overlay.ports?.[vertical.id], `${vertical.id} development port is missing`);
|