@bleedingdev/modern-js-create 3.2.0-ultramodern.59 → 3.2.0-ultramodern.60

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.
@@ -1,935 +0,0 @@
1
- import { execFileSync } from 'node:child_process';
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
-
5
- const root = process.cwd();
6
- const packageScope = '{{packageScope}}';
7
- const tanstackVersion = '1.170.8';
8
- const tailwindEnabled = '{{tailwindEnabled}}' === 'true';
9
- const tailwindVersion = '^4.3.0';
10
- const tailwindPostcssVersion = '^4.3.0';
11
- const expectedPnpmVersion = '{{pnpmVersion}}';
12
- const rstackAgentSkillsCommit = '61c948b42512e223bad44b83af4080eba48b2677';
13
- const moduleFederationAgentSkillsCommit = '07bb5b6c43ad457609e00c081b72d4c42508ec76';
14
- const modernPackages = [
15
- '@modern-js/app-tools',
16
- '@modern-js/plugin-bff',
17
- '@modern-js/plugin-i18n',
18
- '@modern-js/plugin-tanstack',
19
- '@modern-js/runtime',
20
- ];
21
- const baselineAgentSkills = [
22
- 'rsbuild-best-practices',
23
- 'rspack-best-practices',
24
- 'rspack-tracing',
25
- 'rsdoctor-analysis',
26
- 'rslib-best-practices',
27
- 'rslib-modern-package',
28
- 'rstest-best-practices',
29
- ];
30
- const moduleFederationAgentSkills = ['mf'];
31
- const privateAgentSkills = ['plan-graph', 'dag', 'subagent-graph', 'helm', 'debugger-mode'];
32
- const fullStackVerticals = [
33
- {
34
- id: 'commerce',
35
- domain: 'commerce',
36
- stem: 'recommendations',
37
- group: 'recommendations',
38
- path: 'verticals/commerce',
39
- mfName: 'verticalCommerce',
40
- apiPrefix: '/commerce-api',
41
- },
42
- {
43
- id: 'identity',
44
- domain: 'identity',
45
- stem: 'identity',
46
- group: 'identity',
47
- path: 'verticals/identity',
48
- mfName: 'verticalIdentity',
49
- apiPrefix: '/identity-api',
50
- },
51
- ];
52
- const designSystemRemotePath = 'verticals/design-system';
53
-
54
- const readText = (relativePath) => fs.readFileSync(path.join(root, relativePath), 'utf-8');
55
- const readJson = (relativePath) => JSON.parse(readText(relativePath));
56
- const activePnpmVersion = execFileSync('pnpm', ['--version'], {
57
- cwd: root,
58
- encoding: 'utf-8',
59
- stdio: ['ignore', 'pipe', 'pipe'],
60
- }).trim();
61
- const readPnpmConfig = (key) => {
62
- const env = { ...process.env };
63
- for (const envKey of Object.keys(env)) {
64
- if (/^(?:npm|pnpm)_config_/i.test(envKey)) {
65
- delete env[envKey];
66
- }
67
- }
68
- const output = execFileSync('pnpm', ['config', 'get', key, '--json'], {
69
- cwd: root,
70
- env,
71
- encoding: 'utf-8',
72
- stdio: ['ignore', 'pipe', 'pipe'],
73
- }).trim();
74
- return output ? JSON.parse(output) : undefined;
75
- };
76
- const assert = (condition, message) => {
77
- if (!condition) {
78
- throw new Error(message);
79
- }
80
- };
81
- const assertExists = (relativePath) => {
82
- assert(fs.existsSync(path.join(root, relativePath)), `Missing ${relativePath}`);
83
- };
84
- const assertNotExists = (relativePath) => {
85
- assert(!fs.existsSync(path.join(root, relativePath)), `Unexpected ${relativePath}`);
86
- };
87
-
88
- assert(
89
- activePnpmVersion === expectedPnpmVersion,
90
- `Generated workspace requires pnpm ${expectedPnpmVersion}; active pnpm is ${activePnpmVersion}. Run mise install, then rerun pnpm from the activated shell`,
91
- );
92
-
93
- const requiredPaths = [
94
- 'AGENTS.md',
95
- '.gitignore',
96
- 'package.json',
97
- 'pnpm-workspace.yaml',
98
- 'tsconfig.base.json',
99
- 'oxlint.config.ts',
100
- 'oxfmt.config.ts',
101
- 'lefthook.yml',
102
- '.codex/hooks.json',
103
- '.github/renovate.json',
104
- '.github/workflows/ultramodern-workspace-gates.yml',
105
- '.agents/skills-lock.json',
106
- '.agents/agent-reference-repos.json',
107
- '.agents/rstackjs-agent-skills-LICENSE',
108
- '.agents/skills/rsbuild-best-practices/SKILL.md',
109
- '.agents/skills/rspack-best-practices/SKILL.md',
110
- '.agents/skills/rspack-tracing/SKILL.md',
111
- '.agents/skills/rspack-tracing/references/tracing-guide.md',
112
- '.agents/skills/rspack-tracing/scripts/analyze_trace.js',
113
- '.agents/skills/rsdoctor-analysis/SKILL.md',
114
- '.agents/skills/rsdoctor-analysis/references/rsdoctor-data-types.md',
115
- '.agents/skills/rslib-best-practices/SKILL.md',
116
- '.agents/skills/rslib-modern-package/SKILL.md',
117
- '.agents/skills/rstest-best-practices/SKILL.md',
118
- 'topology/reference-topology.json',
119
- 'topology/ownership.json',
120
- 'topology/local-overlays/development.json',
121
- '.modernjs/ultramodern-workspace-template-manifest.json',
122
- '.modernjs/ultramodern-package-source.json',
123
- '.modernjs/ultramodern-generated-contract.json',
124
- 'scripts/assert-mf-types.mjs',
125
- 'scripts/bootstrap-agent-skills.mjs',
126
- 'scripts/setup-agent-reference-repos.mjs',
127
- 'apps/shell-super-app/package.json',
128
- 'apps/shell-super-app/modern.config.ts',
129
- 'apps/shell-super-app/module-federation.config.ts',
130
- 'apps/shell-super-app/src/modern-app-env.d.ts',
131
- 'apps/shell-super-app/src/modern.runtime.ts',
132
- 'apps/shell-super-app/locales/en/translation.json',
133
- 'apps/shell-super-app/locales/cs/translation.json',
134
- 'apps/shell-super-app/src/routes/index.css',
135
- 'apps/shell-super-app/src/routes/layout.tsx',
136
- 'apps/shell-super-app/src/routes/[lang]/page.tsx',
137
- 'verticals/commerce/package.json',
138
- 'verticals/commerce/modern.config.ts',
139
- 'verticals/commerce/module-federation.config.ts',
140
- 'verticals/commerce/api/effect/index.ts',
141
- 'verticals/commerce/shared/effect/api.ts',
142
- 'verticals/commerce/src/effect/recommendations-client.ts',
143
- 'verticals/commerce/src/modern-app-env.d.ts',
144
- 'verticals/commerce/src/modern.runtime.ts',
145
- 'verticals/commerce/locales/en/translation.json',
146
- 'verticals/commerce/locales/cs/translation.json',
147
- 'verticals/commerce/src/routes/index.css',
148
- 'verticals/commerce/src/routes/layout.tsx',
149
- 'verticals/commerce/src/routes/[lang]/page.tsx',
150
- 'verticals/identity/package.json',
151
- 'verticals/identity/modern.config.ts',
152
- 'verticals/identity/module-federation.config.ts',
153
- 'verticals/identity/api/effect/index.ts',
154
- 'verticals/identity/shared/effect/api.ts',
155
- 'verticals/identity/src/effect/identity-client.ts',
156
- 'verticals/identity/src/modern-app-env.d.ts',
157
- 'verticals/identity/src/modern.runtime.ts',
158
- 'verticals/identity/locales/en/translation.json',
159
- 'verticals/identity/locales/cs/translation.json',
160
- 'verticals/identity/src/routes/index.css',
161
- 'verticals/identity/src/routes/layout.tsx',
162
- 'verticals/identity/src/routes/[lang]/page.tsx',
163
- 'verticals/design-system/package.json',
164
- 'verticals/design-system/modern.config.ts',
165
- 'verticals/design-system/module-federation.config.ts',
166
- 'verticals/design-system/src/modern-app-env.d.ts',
167
- 'verticals/design-system/src/modern.runtime.ts',
168
- 'verticals/design-system/locales/en/translation.json',
169
- 'verticals/design-system/locales/cs/translation.json',
170
- 'verticals/design-system/src/routes/index.css',
171
- 'verticals/design-system/src/routes/layout.tsx',
172
- 'verticals/design-system/src/routes/[lang]/page.tsx',
173
- 'packages/shared-contracts/src/index.ts',
174
- 'packages/shared-design-tokens/src/index.ts',
175
- 'packages/shared-effect-api/src/index.ts',
176
- ];
177
-
178
- if (tailwindEnabled) {
179
- requiredPaths.push(
180
- 'apps/shell-super-app/postcss.config.mjs',
181
- 'apps/shell-super-app/tailwind.config.ts',
182
- 'verticals/commerce/postcss.config.mjs',
183
- 'verticals/commerce/tailwind.config.ts',
184
- 'verticals/identity/postcss.config.mjs',
185
- 'verticals/identity/tailwind.config.ts',
186
- 'verticals/design-system/postcss.config.mjs',
187
- 'verticals/design-system/tailwind.config.ts',
188
- );
189
- }
190
-
191
- for (const requiredPath of requiredPaths) {
192
- assertExists(requiredPath);
193
- }
194
-
195
- assertNotExists('services/service-recommendations-effect');
196
-
197
- for (const appDirectory of [
198
- 'apps/shell-super-app',
199
- 'verticals/commerce',
200
- 'verticals/identity',
201
- 'verticals/design-system',
202
- ]) {
203
- assert(
204
- !fs.existsSync(path.join(root, appDirectory, 'src/routes/page.tsx')),
205
- `${appDirectory} must use src/routes/[lang]/page.tsx`,
206
- );
207
- }
208
-
209
- const rootPackage = readJson('package.json');
210
- const packageSource = readJson('.modernjs/ultramodern-package-source.json');
211
- const skillsLock = readJson('.agents/skills-lock.json');
212
- const agentReferenceRepos = readJson('.agents/agent-reference-repos.json');
213
- const workflowContent = readText('.github/workflows/ultramodern-workspace-gates.yml');
214
- const renovateConfig = readJson('.github/renovate.json');
215
- const expectedModernSpecifier =
216
- packageSource.strategy === 'install' ? packageSource.modernPackages?.specifier : 'workspace:*';
217
-
218
- const expectedModernDependency = (packageName) => {
219
- if (packageSource.strategy !== 'install') {
220
- return 'workspace:*';
221
- }
222
-
223
- const aliasPackageName = packageSource.modernPackages?.aliases?.[packageName];
224
- return aliasPackageName
225
- ? `npm:${aliasPackageName}@${expectedModernSpecifier}`
226
- : expectedModernSpecifier;
227
- };
228
-
229
- assert(rootPackage.private === true, 'Root package must be private');
230
- assert(rootPackage.modernjs?.preset === 'presetUltramodern', 'Root must declare presetUltramodern');
231
- const miseConfig = readText('.mise.toml');
232
- assert(
233
- miseConfig.includes(`pnpm = "${expectedPnpmVersion}"`),
234
- `Root must pin pnpm ${expectedPnpmVersion} in .mise.toml`,
235
- );
236
- assert(
237
- rootPackage.packageManager === `pnpm@${expectedPnpmVersion}`,
238
- `Root must pin pnpm ${expectedPnpmVersion}`,
239
- );
240
- assert(
241
- rootPackage.engines?.pnpm === `>=${expectedPnpmVersion} <11.6.0`,
242
- `Root must require pnpm >=${expectedPnpmVersion} <11.6.0`,
243
- );
244
- assert(
245
- JSON.stringify(readPnpmConfig('packages')) ===
246
- JSON.stringify(['apps/*', 'verticals/*', 'packages/*']),
247
- 'pnpm-workspace.yaml must retain workspace package globs',
248
- );
249
- assert(readPnpmConfig('minimumReleaseAge') === 0, 'pnpm minimumReleaseAge must be 0');
250
- assert(readPnpmConfig('minimumReleaseAgeStrict') === undefined, 'pnpm minimumReleaseAgeStrict must stay unset');
251
- assert(
252
- readPnpmConfig('minimumReleaseAgeIgnoreMissingTime') === undefined,
253
- 'pnpm minimumReleaseAgeIgnoreMissingTime must stay unset',
254
- );
255
- assert(
256
- readPnpmConfig('minimumReleaseAgeExclude') === undefined,
257
- 'pnpm minimumReleaseAgeExclude must stay unset',
258
- );
259
- assert(readPnpmConfig('trustPolicy') === undefined, 'pnpm trustPolicy must stay unset');
260
- assert(readPnpmConfig('trustPolicyIgnoreAfter') === undefined, 'pnpm trustPolicyIgnoreAfter must stay unset');
261
- assert(readPnpmConfig('blockExoticSubdeps') === true, 'pnpm blockExoticSubdeps must be true');
262
- assert(readPnpmConfig('engineStrict') === true, 'pnpm engineStrict must be true');
263
- assert(readPnpmConfig('pmOnFail') === 'error', 'pnpm pmOnFail must be error');
264
- assert(readPnpmConfig('verifyDepsBeforeRun') === 'error', 'pnpm verifyDepsBeforeRun must be error');
265
- assert(readPnpmConfig('strictDepBuilds') === true, 'pnpm strictDepBuilds must be true');
266
- assert(
267
- JSON.stringify(readPnpmConfig('peerDependencyRules')) ===
268
- JSON.stringify({ allowedVersions: { react: '>=19.0.0', typescript: '>=6.0.0' } }),
269
- 'pnpm peerDependencyRules must allow React 19 and TypeScript 6+',
270
- );
271
- assert(
272
- JSON.stringify(readPnpmConfig('overrides')) ===
273
- JSON.stringify({ '@tanstack/react-router': '1.170.8', 'node-fetch': '^3.3.2' }),
274
- 'pnpm overrides must pin generated router and node-fetch policy',
275
- );
276
- assert(
277
- JSON.stringify(readPnpmConfig('allowBuilds')) ===
278
- JSON.stringify({
279
- '@swc/core': true,
280
- 'core-js': true,
281
- esbuild: true,
282
- lefthook: true,
283
- 'msgpackr-extract': true,
284
- sharp: true,
285
- workerd: true,
286
- }),
287
- 'pnpm allowBuilds must approve only the generated workspace build dependencies',
288
- );
289
- assert(readPnpmConfig('onlyBuiltDependencies') === undefined, 'pnpm onlyBuiltDependencies must not be set');
290
- for (const requiredSnippet of [
291
- 'permissions:\n contents: read',
292
- 'pull_request:',
293
- 'persist-credentials: false',
294
- 'jdx/mise-action',
295
- 'pnpm install --frozen-lockfile',
296
- 'pnpm run ultramodern:check',
297
- 'pnpm build',
298
- 'MODERN_PUBLIC_SITE_URL: http://localhost:8080',
299
- 'timeout-minutes:',
300
- 'egress-policy: audit',
301
- ]) {
302
- assert(
303
- workflowContent.includes(requiredSnippet),
304
- `Generated workspace workflow must retain ${requiredSnippet.split('\n')[0]}`,
305
- );
306
- }
307
- assert(
308
- !workflowContent.includes('pull_request_target'),
309
- 'Generated workspace workflow must not use pull_request_target',
310
- );
311
- for (const match of workflowContent.matchAll(/^\s*uses:\s*([^@\s]+)@([^\s#]+)/gmu)) {
312
- const [, actionName, actionRef] = match;
313
- assert(
314
- /^[a-f0-9]{40}$/u.test(actionRef),
315
- `Generated workspace workflow must pin ${actionName}@${actionRef} to a commit SHA`,
316
- );
317
- }
318
- assert(
319
- renovateConfig.dependencyDashboard === true &&
320
- renovateConfig.minimumReleaseAge === '1 day' &&
321
- renovateConfig.extends?.includes('helpers:pinGitHubActionDigests') &&
322
- renovateConfig.packageRules?.some(
323
- (rule) =>
324
- rule.dependencyDashboardApproval === true && rule.matchUpdateTypes?.includes('major'),
325
- ),
326
- 'Generated workspace Renovate config must retain dashboard, release-age, action pinning, and major-approval policy',
327
- );
328
- assert(
329
- rootPackage.modernjs?.packageSource?.config === './.modernjs/ultramodern-package-source.json',
330
- 'Root must point to the UltraModern package source metadata',
331
- );
332
- assert(
333
- rootPackage.modernjs?.packageSource?.strategy === packageSource.strategy,
334
- 'Root package source strategy must match the UltraModern package source metadata',
335
- );
336
- assert(
337
- packageSource.strategy === 'workspace' || packageSource.strategy === 'install',
338
- 'Package source strategy must be workspace or install',
339
- );
340
- assert(
341
- packageSource.generatedWorkspacePackages?.specifier === 'workspace:*',
342
- 'Generated shared packages must keep workspace:* links',
343
- );
344
- assert(
345
- modernPackages.every((packageName) =>
346
- packageSource.modernPackages?.packages?.includes(packageName),
347
- ),
348
- 'Package source metadata must list all Modern runtime/tooling packages',
349
- );
350
- assert(
351
- expectedModernSpecifier && packageSource.modernPackages?.specifier === expectedModernSpecifier,
352
- 'Package source metadata must provide a Modern package specifier',
353
- );
354
-
355
- const requiredRootScripts = {
356
- build:
357
- 'pnpm -r --filter "./verticals/**" run build && pnpm --filter "./apps/shell-super-app" run build && pnpm ultramodern:assert-mf-types',
358
- format: 'oxfmt .',
359
- 'format:check': 'oxfmt --check .',
360
- lint: 'oxlint .',
361
- 'lint:fix': 'oxlint . --fix',
362
- 'agents:refs:check': 'node ./scripts/setup-agent-reference-repos.mjs --check',
363
- 'agents:refs:install': 'node ./scripts/setup-agent-reference-repos.mjs',
364
- postinstall:
365
- 'node ./scripts/bootstrap-agent-skills.mjs && (git rev-parse --is-inside-work-tree >/dev/null 2>&1 && lefthook install || true) && node ./scripts/setup-agent-reference-repos.mjs',
366
- 'skills:check': 'node ./scripts/bootstrap-agent-skills.mjs --check',
367
- 'skills:install': 'node ./scripts/bootstrap-agent-skills.mjs',
368
- typecheck: `pnpm -r --filter "@${packageScope}/*" typecheck`,
369
- 'ultramodern:assert-mf-types': 'node ./scripts/assert-mf-types.mjs',
370
- 'ultramodern:check': 'node ./scripts/validate-ultramodern-workspace.mjs',
371
- };
372
- for (const [scriptName, scriptCommand] of Object.entries(requiredRootScripts)) {
373
- assert(rootPackage.scripts?.[scriptName] === scriptCommand, `Root must expose ${scriptName}`);
374
- }
375
- assert(
376
- Object.keys(rootPackage.scripts ?? {}).every((scriptName) => !scriptName.startsWith('zephyr:')),
377
- 'Root package must not expose custom zephyr:* lifecycle commands',
378
- );
379
-
380
- for (const dependency of [
381
- '@effect/tsgo',
382
- '@typescript/native-preview',
383
- 'lefthook',
384
- 'oxfmt',
385
- 'oxlint',
386
- 'ultracite',
387
- ]) {
388
- assert(rootPackage.devDependencies?.[dependency], `Root must depend on ${dependency}`);
389
- }
390
-
391
- const agentsInstructions = readText('AGENTS.md');
392
- assert(
393
- agentsInstructions.includes('UltraModern Agent Contract') &&
394
- agentsInstructions.includes('Required Skill Baseline'),
395
- 'Root AGENTS.md must document the UltraModern agent contract',
396
- );
397
- assert(
398
- skillsLock.source?.repository === 'https://github.com/rstackjs/agent-skills',
399
- 'Agent skills lock must retain the Rstack skill source repository',
400
- );
401
- assert(
402
- skillsLock.source?.commit === rstackAgentSkillsCommit,
403
- 'Agent skills lock must pin the expected Rstack skill commit',
404
- );
405
- assert(
406
- skillsLock.installDir === '.agents/skills',
407
- 'Agent skills lock must use .agents/skills as installDir',
408
- );
409
- assert(
410
- agentReferenceRepos.defaultEnabled === true,
411
- 'Agent reference repositories must be enabled by default',
412
- );
413
- assert(
414
- agentReferenceRepos.strategy === 'git-subtree-squash',
415
- 'Agent reference repositories must use git subtree squash strategy',
416
- );
417
- assert(
418
- agentReferenceRepos.repositories?.some(
419
- (repo) =>
420
- repo.id === 'effect' &&
421
- repo.url === 'https://github.com/Effect-TS/effect.git' &&
422
- repo.path === 'repos/effect',
423
- ),
424
- 'Agent reference repositories must include Effect',
425
- );
426
- assert(
427
- agentReferenceRepos.repositories?.some(
428
- (repo) =>
429
- repo.id === 'ultramodern-js' &&
430
- repo.url === 'https://github.com/BleedingDev/ultramodern.js.git' &&
431
- repo.path === 'repos/ultramodern.js',
432
- ),
433
- 'Agent reference repositories must include UltraModern.js',
434
- );
435
- assert(
436
- readText('scripts/setup-agent-reference-repos.mjs').includes(
437
- 'ULTRAMODERN_SKIP_AGENT_REPOS',
438
- ),
439
- 'Agent reference repository setup must expose an opt-out environment variable',
440
- );
441
- assert(
442
- readText('scripts/setup-agent-reference-repos.mjs').includes('git-subtree-dir'),
443
- 'Agent reference repository setup must validate git subtree evidence',
444
- );
445
- for (const skillName of baselineAgentSkills) {
446
- assert(
447
- skillsLock.baseline?.some((skill) => skill.name === skillName),
448
- `Agent skills lock must include ${skillName}`,
449
- );
450
- assert(
451
- readText(`.agents/skills/${skillName}/SKILL.md`).includes(`name: ${skillName}`),
452
- `${skillName} must contain matching skill metadata`,
453
- );
454
- }
455
-
456
- const privateSource = skillsLock.sources?.find(
457
- (source) => source.repository === 'https://github.com/TechsioCZ/skills',
458
- );
459
- const moduleFederationSource = skillsLock.sources?.find(
460
- (source) => source.repository === 'https://github.com/module-federation/agent-skills',
461
- );
462
- assert(
463
- moduleFederationSource?.install === 'clone' &&
464
- moduleFederationSource.commit === moduleFederationAgentSkillsCommit,
465
- 'Agent skills lock must configure the public Module Federation skill source as a pinned clone',
466
- );
467
- for (const skillName of moduleFederationAgentSkills) {
468
- assert(
469
- skillsLock.baseline?.some((skill) => skill.name === skillName) &&
470
- moduleFederationSource.baseline?.some((skill) => skill.name === skillName),
471
- `Agent skills lock must require Module Federation skill ${skillName}`,
472
- );
473
- assert(
474
- agentsInstructions.includes(`\`${skillName}\``) &&
475
- agentsInstructions.includes('module-federation/agent-skills'),
476
- `Root AGENTS.md must document required Module Federation skill ${skillName}`,
477
- );
478
- }
479
- assert(
480
- privateSource?.install === 'clone-if-authorized',
481
- 'Agent skills lock must configure TechsioCZ skills as clone-if-authorized',
482
- );
483
- for (const skillName of privateAgentSkills) {
484
- assert(
485
- privateSource.baseline?.some((skill) => skill.name === skillName),
486
- `Agent skills lock must pin private skill ${skillName}`,
487
- );
488
- }
489
-
490
- const appPackagePaths = [
491
- 'apps/shell-super-app/package.json',
492
- 'verticals/commerce/package.json',
493
- 'verticals/identity/package.json',
494
- `${designSystemRemotePath}/package.json`,
495
- ];
496
-
497
- const expectedZephyrDependencies = {
498
- commerce: `@${packageScope}/commerce@workspace:*`,
499
- identity: `@${packageScope}/identity@workspace:*`,
500
- designSystem: `@${packageScope}/design-system@workspace:*`,
501
- };
502
-
503
- for (const packagePath of appPackagePaths) {
504
- const packageJson = readJson(packagePath);
505
- const isRemote = packagePath.includes('/verticals/');
506
- const fullStackVertical = fullStackVerticals.find(
507
- (vertical) => `${vertical.path}/package.json` === packagePath,
508
- );
509
- assert(packageJson.scripts?.dev === 'modern dev', `${packagePath} must use vanilla modern dev`);
510
- assert(
511
- packageJson.scripts?.build ===
512
- (isRemote
513
- ? 'modern build && node ../../../scripts/assert-mf-types.mjs'
514
- : 'modern build'),
515
- `${packagePath} must enforce Module Federation DTS on federated builds`,
516
- );
517
- assert(packageJson.scripts?.serve === 'modern serve', `${packagePath} must use vanilla modern serve`);
518
- assert(
519
- Object.keys(packageJson.scripts ?? {}).every((scriptName) => !scriptName.startsWith('zephyr:')),
520
- `${packagePath} must not expose custom zephyr:* lifecycle commands`,
521
- );
522
- assert(
523
- packageJson['zephyr:dependencies'] &&
524
- typeof packageJson['zephyr:dependencies'] === 'object' &&
525
- !Array.isArray(packageJson['zephyr:dependencies']),
526
- `${packagePath} must declare zephyr:dependencies for deterministic Zephyr dependency extraction`,
527
- );
528
- if (isRemote) {
529
- assert(
530
- Object.keys(packageJson['zephyr:dependencies']).length === 0,
531
- `${packagePath} must declare an empty zephyr:dependencies map until it consumes verticals`,
532
- );
533
- } else {
534
- assert(
535
- JSON.stringify(packageJson['zephyr:dependencies']) ===
536
- JSON.stringify(expectedZephyrDependencies),
537
- `${packagePath} must map shell vertical aliases to Zephyr workspace vertical package dependencies`,
538
- );
539
- }
540
- assert(
541
- packageJson.dependencies?.['@modern-js/plugin-tanstack'] ===
542
- expectedModernDependency('@modern-js/plugin-tanstack'),
543
- `${packagePath} must use @modern-js/plugin-tanstack through ${expectedModernDependency(
544
- '@modern-js/plugin-tanstack',
545
- )}`,
546
- );
547
- assert(
548
- packageJson.dependencies?.['@modern-js/plugin-i18n'] ===
549
- expectedModernDependency('@modern-js/plugin-i18n'),
550
- `${packagePath} must use @modern-js/plugin-i18n through ${expectedModernDependency(
551
- '@modern-js/plugin-i18n',
552
- )}`,
553
- );
554
- assert(
555
- packageJson.dependencies?.['@modern-js/runtime'] ===
556
- expectedModernDependency('@modern-js/runtime'),
557
- `${packagePath} must use @modern-js/runtime through ${expectedModernDependency(
558
- '@modern-js/runtime',
559
- )}`,
560
- );
561
- assert(
562
- packageJson.devDependencies?.['@modern-js/app-tools'] ===
563
- expectedModernDependency('@modern-js/app-tools'),
564
- `${packagePath} must use @modern-js/app-tools through ${expectedModernDependency(
565
- '@modern-js/app-tools',
566
- )}`,
567
- );
568
- assert(
569
- packageJson.devDependencies?.typescript === '6.0.3',
570
- `${packagePath} must include TypeScript 6 only as the stable JS TypeScript package for Module Federation DTS generation`,
571
- );
572
- assert(
573
- packageJson.devDependencies?.['@typescript/native-preview'] === '7.0.0-dev.20260527.2',
574
- `${packagePath} must include TypeScript 7 native preview for mandatory native typechecking`,
575
- );
576
- assert(
577
- packageJson.devDependencies?.['zephyr-rspack-plugin'] === '1.1.1',
578
- `${packagePath} must install the Zephyr Rspack plugin used by the Modern.js bridge`,
579
- );
580
- assert(
581
- packageJson.devDependencies?.['zephyr-modernjs-plugin'] === undefined,
582
- `${packagePath} must not install the inactive Zephyr Modern.js wrapper`,
583
- );
584
- assert(
585
- packageJson.dependencies?.[`@${packageScope}/shared-contracts`] === 'workspace:*',
586
- `${packagePath} must link generated shared contracts through workspace:*`,
587
- );
588
- assert(
589
- packageJson.dependencies?.[`@${packageScope}/shared-design-tokens`] === 'workspace:*',
590
- `${packagePath} must link generated shared design tokens through workspace:*`,
591
- );
592
- assert(
593
- packageJson.dependencies?.['node-fetch'] === '^3.3.2',
594
- `${packagePath} must satisfy the Module Federation SDK node-fetch peer`,
595
- );
596
- assert(
597
- packageJson.dependencies?.['@tanstack/react-router'] === tanstackVersion,
598
- `${packagePath} must use @tanstack/react-router ${tanstackVersion}`,
599
- );
600
- assert(
601
- packageJson.dependencies?.i18next === '26.2.0',
602
- `${packagePath} must include i18next for mandatory native Modern.js i18n`,
603
- );
604
- assert(
605
- !packageJson.dependencies?.['react-i18next'],
606
- `${packagePath} must use native @modern-js/plugin-i18n hooks instead of react-i18next in the TanStack MF starter`,
607
- );
608
- assert(
609
- packageJson.dependencies?.['@module-federation/modern-js-v3'] === '2.5.0',
610
- `${packagePath} must include the Module Federation plugin`,
611
- );
612
- if (fullStackVertical) {
613
- assert(
614
- packageJson.dependencies?.['@modern-js/plugin-bff'] ===
615
- expectedModernDependency('@modern-js/plugin-bff'),
616
- `${packagePath} must use @modern-js/plugin-bff through ${expectedModernDependency(
617
- '@modern-js/plugin-bff',
618
- )}`,
619
- );
620
- assert(
621
- packageJson.exports?.['./effect/client'] ===
622
- `./src/effect/${fullStackVertical.stem}-client.ts` &&
623
- packageJson.exports?.['./shared/effect/api'] === './shared/effect/api.ts',
624
- `${packagePath} must expose its vertical-owned Effect client and contract surface`,
625
- );
626
- }
627
- if (packagePath === `${designSystemRemotePath}/package.json`) {
628
- assert(
629
- !packageJson.dependencies?.['@modern-js/plugin-bff'],
630
- 'Design-system vertical must remain FE-only and must not depend on @modern-js/plugin-bff',
631
- );
632
- assert(
633
- !packageJson.exports?.['./effect/client'] && !packageJson.exports?.['./shared/effect/api'],
634
- 'Design-system vertical must not expose Effect client or contract exports',
635
- );
636
- }
637
- if (tailwindEnabled) {
638
- assert(
639
- packageJson.devDependencies?.tailwindcss === tailwindVersion,
640
- `${packagePath} must include Tailwind CSS ${tailwindVersion}`,
641
- );
642
- assert(
643
- packageJson.devDependencies?.['@tailwindcss/postcss'] === tailwindPostcssVersion,
644
- `${packagePath} must include @tailwindcss/postcss ${tailwindPostcssVersion}`,
645
- );
646
- assert(
647
- packageJson.devDependencies?.postcss === '^8.5.6',
648
- `${packagePath} must include PostCSS for Tailwind CSS`,
649
- );
650
- } else {
651
- assert(!packageJson.devDependencies?.tailwindcss, `${packagePath} must not include Tailwind CSS`);
652
- assert(
653
- !packageJson.devDependencies?.['@tailwindcss/postcss'],
654
- `${packagePath} must not include @tailwindcss/postcss`,
655
- );
656
- }
657
- assert(
658
- packageJson.modernjs?.preset === 'presetUltramodern',
659
- `${packagePath} must keep presetUltramodern metadata`,
660
- );
661
- }
662
-
663
- for (const federationConfigPath of [
664
- 'apps/shell-super-app/module-federation.config.ts',
665
- 'verticals/commerce/module-federation.config.ts',
666
- 'verticals/identity/module-federation.config.ts',
667
- 'verticals/design-system/module-federation.config.ts',
668
- ]) {
669
- const federationConfig = readText(federationConfigPath);
670
- assert(
671
- federationConfig.includes('compilerInstance:') &&
672
- federationConfig.includes("'--package typescript -- tsc'") &&
673
- federationConfig.includes('displayErrorInTerminal: true') &&
674
- !federationConfig.includes('dts: false'),
675
- `${federationConfigPath} must keep strict Module Federation DTS enabled`,
676
- );
677
- }
678
-
679
- for (const appDirectory of [
680
- 'apps/shell-super-app',
681
- 'verticals/commerce',
682
- 'verticals/identity',
683
- 'verticals/design-system',
684
- ]) {
685
- if (tailwindEnabled) {
686
- assertExists(`${appDirectory}/postcss.config.mjs`);
687
- assertExists(`${appDirectory}/tailwind.config.ts`);
688
- }
689
- if (!tailwindEnabled) {
690
- assert(
691
- !fs.existsSync(path.join(root, appDirectory, 'postcss.config.mjs')),
692
- `${appDirectory} must not write PostCSS config when Tailwind is disabled`,
693
- );
694
- assert(
695
- !fs.existsSync(path.join(root, appDirectory, 'tailwind.config.ts')),
696
- `${appDirectory} must not write Tailwind config when Tailwind is disabled`,
697
- );
698
- }
699
- }
700
-
701
- for (const configPath of [
702
- 'apps/shell-super-app/modern.config.ts',
703
- 'verticals/commerce/modern.config.ts',
704
- 'verticals/identity/modern.config.ts',
705
- 'verticals/design-system/modern.config.ts',
706
- ]) {
707
- const config = readText(configPath);
708
- assert(config.includes('presetUltramodern('), `${configPath} must use presetUltramodern`);
709
- assert(config.includes('ULTRAMODERN_SITE_URL'), `${configPath} must expose site URL metadata`);
710
- assert(
711
- config.includes('MODERN_PUBLIC_SITE_URL must be set for production builds'),
712
- `${configPath} must require MODERN_PUBLIC_SITE_URL for production builds`,
713
- );
714
- assert(config.includes('tanstackRouterPlugin()'), `${configPath} must enable plugin-tanstack`);
715
- assert(config.includes('i18nPlugin('), `${configPath} must enable native Modern.js i18n`);
716
- assert(
717
- config.includes('reactI18next: false'),
718
- `${configPath} must use the native Modern.js i18n provider without optional react-i18next probing`,
719
- );
720
- assert(
721
- config.includes("publicDir: './locales'"),
722
- `${configPath} must expose app-owned locale JSON through Modern.js publicDir`,
723
- );
724
- assert(
725
- config.includes('moduleFederationPlugin()'),
726
- `${configPath} must enable Module Federation`,
727
- );
728
- assert(
729
- config.includes("mode: 'stream'") &&
730
- config.includes('moduleFederationAppSSR: true'),
731
- `${configPath} must use streaming Module Federation SSR`,
732
- );
733
- assert(
734
- config.includes("html: './'"),
735
- `${configPath} must keep Modern.js output.distPath.html compatible with Zephyr`,
736
- );
737
- assert(
738
- config.includes("outputStructure: 'flat'"),
739
- `${configPath} must keep Modern.js HTML output flat for Zephyr`,
740
- );
741
- assert(
742
- config.includes("mainEntryName: 'index'"),
743
- `${configPath} must keep Modern.js source.mainEntryName compatible with Zephyr`,
744
- );
745
- }
746
-
747
- const shellMf = readText('apps/shell-super-app/module-federation.config.ts');
748
- assert(shellMf.includes("name: 'shellSuperApp'"), 'Shell MF config must name the shell');
749
- assert(
750
- shellMf.includes("'react-dom/client'"),
751
- 'Shell MF config must share react-dom/client explicitly',
752
- );
753
- assert(
754
- shellMf.includes('verticalCommerce@http://localhost:3021/mf-manifest.json'),
755
- 'Shell must reference commerce vertical',
756
- );
757
- assert(
758
- shellMf.includes('verticalIdentity@http://localhost:3022/mf-manifest.json'),
759
- 'Shell must reference identity vertical',
760
- );
761
- assert(
762
- shellMf.includes('verticalDesignSystem@http://localhost:3023/mf-manifest.json'),
763
- 'Shell must reference design-system vertical',
764
- );
765
-
766
- const shellPackage = readJson('apps/shell-super-app/package.json');
767
- assert(
768
- shellPackage.dependencies?.['@modern-js/plugin-bff'] ===
769
- expectedModernDependency('@modern-js/plugin-bff'),
770
- `Shell must use @modern-js/plugin-bff through ${expectedModernDependency(
771
- '@modern-js/plugin-bff',
772
- )}`,
773
- );
774
- assert(
775
- !shellPackage.dependencies?.[`@${packageScope}/shared-effect-api`],
776
- 'Shell must not depend on shared-effect-api for default vertical-owned APIs',
777
- );
778
-
779
- const generatedContract = readJson('.modernjs/ultramodern-generated-contract.json');
780
- assert(
781
- generatedContract.profile === 'cloudflare-ssr-mf-effect-v1',
782
- 'Generated contract must select the Cloudflare SSR MF Effect profile',
783
- );
784
- assert(
785
- generatedContract.packageManager?.manager === 'pnpm' &&
786
- generatedContract.packageManager?.version === expectedPnpmVersion &&
787
- generatedContract.packageManager?.toolchain === 'mise',
788
- 'Generated contract must declare the pnpm 11/mise toolchain policy',
789
- );
790
-
791
- for (const vertical of fullStackVerticals) {
792
- const contractEntry = generatedContract.apps?.find((app) => app.id === vertical.id);
793
- assert(
794
- contractEntry?.deploy?.target === 'cloudflare' &&
795
- contractEntry?.deploy?.worker?.ssr === true &&
796
- contractEntry?.deploy?.output?.flat === true &&
797
- contractEntry?.deploy?.output?.htmlDistPath === './' &&
798
- contractEntry?.ssr?.mode === 'stream' &&
799
- contractEntry?.ssr?.moduleFederationAppSSR === true &&
800
- contractEntry?.i18n?.plugin === '@modern-js/plugin-i18n' &&
801
- contractEntry?.i18n?.languages?.includes('en') &&
802
- contractEntry?.i18n?.languages?.includes('cs') &&
803
- contractEntry?.moduleFederation?.name === vertical.mfName &&
804
- contractEntry?.moduleFederation?.exposes?.includes('./Widget') &&
805
- contractEntry?.moduleFederation?.exposes?.includes('./Route') &&
806
- contractEntry?.moduleFederation?.browserSafeExposesOnly === true &&
807
- contractEntry?.effect?.runtime === 'effect' &&
808
- contractEntry?.effect?.import === '@modern-js/plugin-bff/effect-edge' &&
809
- contractEntry?.effect?.prefix === vertical.apiPrefix &&
810
- contractEntry?.effect?.workerEntry === 'worker/__modern_bff_effect.js' &&
811
- contractEntry?.marker?.appId === vertical.id &&
812
- contractEntry?.marker?.deployProfile === 'cloudflare-ssr-mf-effect-v1' &&
813
- contractEntry?.marker?.uiSurface === 'ui' &&
814
- contractEntry?.marker?.apiSurface === 'effect-bff',
815
- `${vertical.id} generated contract must describe Cloudflare SSR, MF, i18n, Effect BFF, and marker metadata`,
816
- );
817
- }
818
-
819
- const designMf = readText('verticals/design-system/module-federation.config.ts');
820
- assert(designMf.includes("name: 'verticalDesignSystem'"), 'Design-system federated MF name is missing');
821
- assert(
822
- designMf.includes("'react-dom/client'"),
823
- 'Design-system federated MF config must share react-dom/client explicitly',
824
- );
825
- assert(designMf.includes("'./Button'"), 'Design-system vertical must expose Button');
826
- assert(designMf.includes("'./tokens'"), 'Design-system vertical must expose tokens');
827
- const sharedEffectApi = readText('packages/shared-effect-api/src/index.ts');
828
- assert(
829
- !sharedEffectApi.includes('recommendationsEffectApi') &&
830
- !sharedEffectApi.includes('commerceEffectApi') &&
831
- !sharedEffectApi.includes('identityEffectApi'),
832
- 'Shared Effect API package must not own default vertical API contracts',
833
- );
834
-
835
- const topology = readJson('topology/reference-topology.json');
836
- assert(topology.preset === 'presetUltramodern', 'Topology must reference presetUltramodern');
837
- assert(topology.shell?.id === 'shell-super-app', 'Topology shell id is incorrect');
838
- assert(topology.shell?.verticalRefs?.length === 3, 'Topology shell must reference three verticals');
839
- assert(topology.verticals?.length === 3, 'Topology must contain three verticals');
840
- for (const vertical of fullStackVerticals) {
841
- const topologyEntry = topology.verticals.find((vertical) => vertical.id === vertical.id);
842
- assert(topologyEntry?.kind === 'vertical', `${vertical.id} must be a vertical topology entry`);
843
- assert(
844
- topologyEntry?.moduleFederation?.manifestUrl?.includes('/mf-manifest.json') &&
845
- topologyEntry?.api?.effect?.runtime === 'effect' &&
846
- topologyEntry?.api?.effect?.bff?.prefix === vertical.apiPrefix &&
847
- topologyEntry?.api?.effect?.bff?.openapi === '/openapi.json' &&
848
- topologyEntry?.api?.effect?.contract?.export === './shared/effect/api' &&
849
- topologyEntry?.api?.effect?.client?.export === './effect/client' &&
850
- topologyEntry?.api?.effect?.serverEntry === `${vertical.path}/api/effect/index.ts`,
851
- `${vertical.id} topology entry must include both Module Federation and Effect API metadata`,
852
- );
853
- }
854
- assert(
855
- topology.verticals.some(
856
- (vertical) => vertical.id === 'design-system' && vertical.kind === 'vertical',
857
- ),
858
- 'Topology must contain the horizontal design-system vertical',
859
- );
860
- assert(
861
- !('effectServices' in topology),
862
- 'Topology must not expose effectServices; vertical APIs are owned by vertical packages',
863
- );
864
- assert(topology.sharedPackages?.length === 3, 'Topology must contain shared package placeholders');
865
-
866
- const ownership = readJson('topology/ownership.json');
867
- assert(
868
- ownership.owners?.some(
869
- (owner) => owner.id === 'commerce' && owner.ownership?.team === 'commerce-experience',
870
- ),
871
- 'Ownership metadata must retain commerce owner',
872
- );
873
- assert(
874
- !ownership.owners?.some(
875
- (owner) =>
876
- owner.id === 'service-recommendations-effect' ||
877
- owner.path === 'services/service-recommendations-effect',
878
- ),
879
- 'Ownership metadata must not retain the old default recommendations service owner',
880
- );
881
-
882
- const manifest = readJson('.modernjs/ultramodern-workspace-template-manifest.json');
883
- assert(
884
- manifest.template?.id === 'modernjs-ultramodern-superapp-workspace',
885
- 'Template manifest evidence is missing',
886
- );
887
- assert(
888
- manifest.packageSource?.strategy === packageSource.strategy,
889
- 'Template manifest must retain the generated package source strategy',
890
- );
891
- assert(
892
- manifest.agentSkills?.source?.commit === rstackAgentSkillsCommit,
893
- 'Template manifest must retain the Rstack agent skills commit',
894
- );
895
- assert(
896
- baselineAgentSkills.every((skillName) => manifest.agentSkills?.baseline?.includes(skillName)),
897
- 'Template manifest must list every baseline agent skill',
898
- );
899
- assert(
900
- manifest.agentSkills?.moduleFederationSource?.repository ===
901
- 'https://github.com/module-federation/agent-skills' &&
902
- manifest.agentSkills?.moduleFederationSource?.commit ===
903
- moduleFederationAgentSkillsCommit,
904
- 'Template manifest must retain the Module Federation agent skill source',
905
- );
906
- assert(
907
- moduleFederationAgentSkills.every((skillName) =>
908
- manifest.agentSkills?.moduleFederationSource?.baseline?.includes(skillName),
909
- ),
910
- 'Template manifest must list every Module Federation agent skill entry',
911
- );
912
- assert(
913
- manifest.agentSkills?.privateSource?.repository === 'https://github.com/TechsioCZ/skills',
914
- 'Template manifest must retain the private TechsioCZ skill source',
915
- );
916
- assert(
917
- privateAgentSkills.every((skillName) =>
918
- manifest.agentSkills?.privateSource?.baseline?.includes(skillName),
919
- ),
920
- 'Template manifest must list every pinned private agent skill entry',
921
- );
922
- assert(
923
- manifest.validation?.expectedCommands?.includes('pnpm run ultramodern:check'),
924
- 'Template manifest must document the validation command',
925
- );
926
- assert(
927
- manifest.validation?.postMaterializationValidation?.includes('pnpm-11-policy-enforced'),
928
- 'Template manifest must document pnpm 11 policy validation',
929
- );
930
- assert(
931
- manifest.validation?.postMaterializationValidation?.includes('github-workflow-security-enforced'),
932
- 'Template manifest must document generated workflow security validation',
933
- );
934
-
935
- console.log('UltraModern workspace scaffold validated');