@bleedingdev/modern-js-create 3.2.0-ultramodern.58 → 3.2.0-ultramodern.59
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 +30 -39
- package/dist/index.js +670 -702
- package/dist/types/locale/en.d.ts +1 -1
- package/dist/types/locale/zh.d.ts +1 -1
- package/dist/types/ultramodern-workspace.d.ts +2 -4
- package/package.json +1 -1
- package/template/.codex/hooks.json +16 -0
- package/template/AGENTS.md +4 -8
- package/template/README.md +40 -43
- package/template/lefthook.yml +15 -0
- package/template/package.json.handlebars +5 -15
- package/template/pnpm-workspace.yaml +1 -1
- package/template/scripts/bootstrap-agent-skills.mjs +39 -7
- package/template/scripts/validate-ultramodern.mjs.handlebars +18 -8
- package/template/src/routes/[lang]/page.tsx.handlebars +1 -1
- package/template-workspace/.codex/hooks.json +16 -0
- package/template-workspace/AGENTS.md +4 -2
- package/template-workspace/README.md.handlebars +10 -11
- package/template-workspace/lefthook.yml +15 -0
- package/template-workspace/pnpm-workspace.yaml +2 -3
- package/template-workspace/scripts/assert-mf-types.mjs +3 -3
- package/template-workspace/scripts/setup-agent-reference-repos.mjs +6 -2
- package/template-workspace/scripts/validate-ultramodern-workspace.mjs.handlebars +106 -103
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
packages:
|
|
2
2
|
- apps/*
|
|
3
|
-
-
|
|
4
|
-
- services/*
|
|
3
|
+
- verticals/*
|
|
5
4
|
- packages/*
|
|
6
5
|
|
|
7
6
|
minimumReleaseAge: 0
|
|
@@ -24,7 +23,7 @@ allowBuilds:
|
|
|
24
23
|
'@swc/core': true
|
|
25
24
|
core-js: true
|
|
26
25
|
esbuild: true
|
|
26
|
+
lefthook: true
|
|
27
27
|
msgpackr-extract: true
|
|
28
28
|
sharp: true
|
|
29
|
-
simple-git-hooks: true
|
|
30
29
|
workerd: true
|
|
@@ -3,9 +3,9 @@ import path from 'node:path';
|
|
|
3
3
|
|
|
4
4
|
const root = process.cwd();
|
|
5
5
|
const defaultAppDirs = [
|
|
6
|
-
'
|
|
7
|
-
'
|
|
8
|
-
'
|
|
6
|
+
'verticals/commerce',
|
|
7
|
+
'verticals/identity',
|
|
8
|
+
'verticals/design-system',
|
|
9
9
|
];
|
|
10
10
|
|
|
11
11
|
const candidateDirs = process.argv.slice(2);
|
|
@@ -359,6 +359,10 @@ function main() {
|
|
|
359
359
|
try {
|
|
360
360
|
main();
|
|
361
361
|
} catch (error) {
|
|
362
|
-
|
|
363
|
-
|
|
362
|
+
if (required || checkOnly) {
|
|
363
|
+
console.error(`[agent-reference-repos] ${error.message}`);
|
|
364
|
+
process.exitCode = 1;
|
|
365
|
+
} else {
|
|
366
|
+
warn(error.message);
|
|
367
|
+
}
|
|
364
368
|
}
|
|
@@ -31,25 +31,25 @@ const moduleFederationAgentSkills = ['mf'];
|
|
|
31
31
|
const privateAgentSkills = ['plan-graph', 'dag', 'subagent-graph', 'helm', 'debugger-mode'];
|
|
32
32
|
const fullStackVerticals = [
|
|
33
33
|
{
|
|
34
|
-
id: '
|
|
34
|
+
id: 'commerce',
|
|
35
35
|
domain: 'commerce',
|
|
36
36
|
stem: 'recommendations',
|
|
37
37
|
group: 'recommendations',
|
|
38
|
-
path: '
|
|
39
|
-
mfName: '
|
|
38
|
+
path: 'verticals/commerce',
|
|
39
|
+
mfName: 'verticalCommerce',
|
|
40
40
|
apiPrefix: '/commerce-api',
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
|
-
id: '
|
|
43
|
+
id: 'identity',
|
|
44
44
|
domain: 'identity',
|
|
45
45
|
stem: 'identity',
|
|
46
46
|
group: 'identity',
|
|
47
|
-
path: '
|
|
48
|
-
mfName: '
|
|
47
|
+
path: 'verticals/identity',
|
|
48
|
+
mfName: 'verticalIdentity',
|
|
49
49
|
apiPrefix: '/identity-api',
|
|
50
50
|
},
|
|
51
51
|
];
|
|
52
|
-
const designSystemRemotePath = '
|
|
52
|
+
const designSystemRemotePath = 'verticals/design-system';
|
|
53
53
|
|
|
54
54
|
const readText = (relativePath) => fs.readFileSync(path.join(root, relativePath), 'utf-8');
|
|
55
55
|
const readJson = (relativePath) => JSON.parse(readText(relativePath));
|
|
@@ -87,7 +87,7 @@ const assertNotExists = (relativePath) => {
|
|
|
87
87
|
|
|
88
88
|
assert(
|
|
89
89
|
activePnpmVersion === expectedPnpmVersion,
|
|
90
|
-
`Generated workspace requires pnpm ${expectedPnpmVersion}; active pnpm is ${activePnpmVersion}. Run mise install, then rerun
|
|
90
|
+
`Generated workspace requires pnpm ${expectedPnpmVersion}; active pnpm is ${activePnpmVersion}. Run mise install, then rerun pnpm from the activated shell`,
|
|
91
91
|
);
|
|
92
92
|
|
|
93
93
|
const requiredPaths = [
|
|
@@ -98,6 +98,8 @@ const requiredPaths = [
|
|
|
98
98
|
'tsconfig.base.json',
|
|
99
99
|
'oxlint.config.ts',
|
|
100
100
|
'oxfmt.config.ts',
|
|
101
|
+
'lefthook.yml',
|
|
102
|
+
'.codex/hooks.json',
|
|
101
103
|
'.github/renovate.json',
|
|
102
104
|
'.github/workflows/ultramodern-workspace-gates.yml',
|
|
103
105
|
'.agents/skills-lock.json',
|
|
@@ -132,42 +134,42 @@ const requiredPaths = [
|
|
|
132
134
|
'apps/shell-super-app/src/routes/index.css',
|
|
133
135
|
'apps/shell-super-app/src/routes/layout.tsx',
|
|
134
136
|
'apps/shell-super-app/src/routes/[lang]/page.tsx',
|
|
135
|
-
'
|
|
136
|
-
'
|
|
137
|
-
'
|
|
138
|
-
'
|
|
139
|
-
'
|
|
140
|
-
'
|
|
141
|
-
'
|
|
142
|
-
'
|
|
143
|
-
'
|
|
144
|
-
'
|
|
145
|
-
'
|
|
146
|
-
'
|
|
147
|
-
'
|
|
148
|
-
'
|
|
149
|
-
'
|
|
150
|
-
'
|
|
151
|
-
'
|
|
152
|
-
'
|
|
153
|
-
'
|
|
154
|
-
'
|
|
155
|
-
'
|
|
156
|
-
'
|
|
157
|
-
'
|
|
158
|
-
'
|
|
159
|
-
'
|
|
160
|
-
'
|
|
161
|
-
'
|
|
162
|
-
'
|
|
163
|
-
'
|
|
164
|
-
'
|
|
165
|
-
'
|
|
166
|
-
'
|
|
167
|
-
'
|
|
168
|
-
'
|
|
169
|
-
'
|
|
170
|
-
'
|
|
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',
|
|
171
173
|
'packages/shared-contracts/src/index.ts',
|
|
172
174
|
'packages/shared-design-tokens/src/index.ts',
|
|
173
175
|
'packages/shared-effect-api/src/index.ts',
|
|
@@ -177,12 +179,12 @@ if (tailwindEnabled) {
|
|
|
177
179
|
requiredPaths.push(
|
|
178
180
|
'apps/shell-super-app/postcss.config.mjs',
|
|
179
181
|
'apps/shell-super-app/tailwind.config.ts',
|
|
180
|
-
'
|
|
181
|
-
'
|
|
182
|
-
'
|
|
183
|
-
'
|
|
184
|
-
'
|
|
185
|
-
'
|
|
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',
|
|
186
188
|
);
|
|
187
189
|
}
|
|
188
190
|
|
|
@@ -194,9 +196,9 @@ assertNotExists('services/service-recommendations-effect');
|
|
|
194
196
|
|
|
195
197
|
for (const appDirectory of [
|
|
196
198
|
'apps/shell-super-app',
|
|
197
|
-
'
|
|
198
|
-
'
|
|
199
|
-
'
|
|
199
|
+
'verticals/commerce',
|
|
200
|
+
'verticals/identity',
|
|
201
|
+
'verticals/design-system',
|
|
200
202
|
]) {
|
|
201
203
|
assert(
|
|
202
204
|
!fs.existsSync(path.join(root, appDirectory, 'src/routes/page.tsx')),
|
|
@@ -236,12 +238,12 @@ assert(
|
|
|
236
238
|
`Root must pin pnpm ${expectedPnpmVersion}`,
|
|
237
239
|
);
|
|
238
240
|
assert(
|
|
239
|
-
rootPackage.engines?.pnpm === `>=${expectedPnpmVersion} <11.
|
|
240
|
-
`Root must require pnpm >=${expectedPnpmVersion} <11.
|
|
241
|
+
rootPackage.engines?.pnpm === `>=${expectedPnpmVersion} <11.6.0`,
|
|
242
|
+
`Root must require pnpm >=${expectedPnpmVersion} <11.6.0`,
|
|
241
243
|
);
|
|
242
244
|
assert(
|
|
243
245
|
JSON.stringify(readPnpmConfig('packages')) ===
|
|
244
|
-
JSON.stringify(['apps/*', '
|
|
246
|
+
JSON.stringify(['apps/*', 'verticals/*', 'packages/*']),
|
|
245
247
|
'pnpm-workspace.yaml must retain workspace package globs',
|
|
246
248
|
);
|
|
247
249
|
assert(readPnpmConfig('minimumReleaseAge') === 0, 'pnpm minimumReleaseAge must be 0');
|
|
@@ -277,9 +279,9 @@ assert(
|
|
|
277
279
|
'@swc/core': true,
|
|
278
280
|
'core-js': true,
|
|
279
281
|
esbuild: true,
|
|
282
|
+
lefthook: true,
|
|
280
283
|
'msgpackr-extract': true,
|
|
281
284
|
sharp: true,
|
|
282
|
-
'simple-git-hooks': true,
|
|
283
285
|
workerd: true,
|
|
284
286
|
}),
|
|
285
287
|
'pnpm allowBuilds must approve only the generated workspace build dependencies',
|
|
@@ -290,9 +292,9 @@ for (const requiredSnippet of [
|
|
|
290
292
|
'pull_request:',
|
|
291
293
|
'persist-credentials: false',
|
|
292
294
|
'jdx/mise-action',
|
|
293
|
-
'
|
|
294
|
-
'
|
|
295
|
-
'
|
|
295
|
+
'pnpm install --frozen-lockfile',
|
|
296
|
+
'pnpm run ultramodern:check',
|
|
297
|
+
'pnpm build',
|
|
296
298
|
'MODERN_PUBLIC_SITE_URL: http://localhost:8080',
|
|
297
299
|
'timeout-minutes:',
|
|
298
300
|
'egress-policy: audit',
|
|
@@ -352,7 +354,7 @@ assert(
|
|
|
352
354
|
|
|
353
355
|
const requiredRootScripts = {
|
|
354
356
|
build:
|
|
355
|
-
'pnpm -r --filter "./
|
|
357
|
+
'pnpm -r --filter "./verticals/**" run build && pnpm --filter "./apps/shell-super-app" run build && pnpm ultramodern:assert-mf-types',
|
|
356
358
|
format: 'oxfmt .',
|
|
357
359
|
'format:check': 'oxfmt --check .',
|
|
358
360
|
lint: 'oxlint .',
|
|
@@ -360,7 +362,7 @@ const requiredRootScripts = {
|
|
|
360
362
|
'agents:refs:check': 'node ./scripts/setup-agent-reference-repos.mjs --check',
|
|
361
363
|
'agents:refs:install': 'node ./scripts/setup-agent-reference-repos.mjs',
|
|
362
364
|
postinstall:
|
|
363
|
-
'node ./scripts/
|
|
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',
|
|
364
366
|
'skills:check': 'node ./scripts/bootstrap-agent-skills.mjs --check',
|
|
365
367
|
'skills:install': 'node ./scripts/bootstrap-agent-skills.mjs',
|
|
366
368
|
typecheck: `pnpm -r --filter "@${packageScope}/*" typecheck`,
|
|
@@ -378,6 +380,7 @@ assert(
|
|
|
378
380
|
for (const dependency of [
|
|
379
381
|
'@effect/tsgo',
|
|
380
382
|
'@typescript/native-preview',
|
|
383
|
+
'lefthook',
|
|
381
384
|
'oxfmt',
|
|
382
385
|
'oxlint',
|
|
383
386
|
'ultracite',
|
|
@@ -486,20 +489,20 @@ for (const skillName of privateAgentSkills) {
|
|
|
486
489
|
|
|
487
490
|
const appPackagePaths = [
|
|
488
491
|
'apps/shell-super-app/package.json',
|
|
489
|
-
'
|
|
490
|
-
'
|
|
492
|
+
'verticals/commerce/package.json',
|
|
493
|
+
'verticals/identity/package.json',
|
|
491
494
|
`${designSystemRemotePath}/package.json`,
|
|
492
495
|
];
|
|
493
496
|
|
|
494
497
|
const expectedZephyrDependencies = {
|
|
495
|
-
commerce: `@${packageScope}/
|
|
496
|
-
identity: `@${packageScope}/
|
|
497
|
-
designSystem: `@${packageScope}/
|
|
498
|
+
commerce: `@${packageScope}/commerce@workspace:*`,
|
|
499
|
+
identity: `@${packageScope}/identity@workspace:*`,
|
|
500
|
+
designSystem: `@${packageScope}/design-system@workspace:*`,
|
|
498
501
|
};
|
|
499
502
|
|
|
500
503
|
for (const packagePath of appPackagePaths) {
|
|
501
504
|
const packageJson = readJson(packagePath);
|
|
502
|
-
const isRemote = packagePath.includes('/
|
|
505
|
+
const isRemote = packagePath.includes('/verticals/');
|
|
503
506
|
const fullStackVertical = fullStackVerticals.find(
|
|
504
507
|
(vertical) => `${vertical.path}/package.json` === packagePath,
|
|
505
508
|
);
|
|
@@ -509,7 +512,7 @@ for (const packagePath of appPackagePaths) {
|
|
|
509
512
|
(isRemote
|
|
510
513
|
? 'modern build && node ../../../scripts/assert-mf-types.mjs'
|
|
511
514
|
: 'modern build'),
|
|
512
|
-
`${packagePath} must enforce Module Federation DTS on
|
|
515
|
+
`${packagePath} must enforce Module Federation DTS on federated builds`,
|
|
513
516
|
);
|
|
514
517
|
assert(packageJson.scripts?.serve === 'modern serve', `${packagePath} must use vanilla modern serve`);
|
|
515
518
|
assert(
|
|
@@ -525,13 +528,13 @@ for (const packagePath of appPackagePaths) {
|
|
|
525
528
|
if (isRemote) {
|
|
526
529
|
assert(
|
|
527
530
|
Object.keys(packageJson['zephyr:dependencies']).length === 0,
|
|
528
|
-
`${packagePath} must declare an empty zephyr:dependencies map until it consumes
|
|
531
|
+
`${packagePath} must declare an empty zephyr:dependencies map until it consumes verticals`,
|
|
529
532
|
);
|
|
530
533
|
} else {
|
|
531
534
|
assert(
|
|
532
535
|
JSON.stringify(packageJson['zephyr:dependencies']) ===
|
|
533
536
|
JSON.stringify(expectedZephyrDependencies),
|
|
534
|
-
`${packagePath} must map shell
|
|
537
|
+
`${packagePath} must map shell vertical aliases to Zephyr workspace vertical package dependencies`,
|
|
535
538
|
);
|
|
536
539
|
}
|
|
537
540
|
assert(
|
|
@@ -624,11 +627,11 @@ for (const packagePath of appPackagePaths) {
|
|
|
624
627
|
if (packagePath === `${designSystemRemotePath}/package.json`) {
|
|
625
628
|
assert(
|
|
626
629
|
!packageJson.dependencies?.['@modern-js/plugin-bff'],
|
|
627
|
-
'Design-system
|
|
630
|
+
'Design-system vertical must remain FE-only and must not depend on @modern-js/plugin-bff',
|
|
628
631
|
);
|
|
629
632
|
assert(
|
|
630
633
|
!packageJson.exports?.['./effect/client'] && !packageJson.exports?.['./shared/effect/api'],
|
|
631
|
-
'Design-system
|
|
634
|
+
'Design-system vertical must not expose Effect client or contract exports',
|
|
632
635
|
);
|
|
633
636
|
}
|
|
634
637
|
if (tailwindEnabled) {
|
|
@@ -659,9 +662,9 @@ for (const packagePath of appPackagePaths) {
|
|
|
659
662
|
|
|
660
663
|
for (const federationConfigPath of [
|
|
661
664
|
'apps/shell-super-app/module-federation.config.ts',
|
|
662
|
-
'
|
|
663
|
-
'
|
|
664
|
-
'
|
|
665
|
+
'verticals/commerce/module-federation.config.ts',
|
|
666
|
+
'verticals/identity/module-federation.config.ts',
|
|
667
|
+
'verticals/design-system/module-federation.config.ts',
|
|
665
668
|
]) {
|
|
666
669
|
const federationConfig = readText(federationConfigPath);
|
|
667
670
|
assert(
|
|
@@ -675,9 +678,9 @@ for (const federationConfigPath of [
|
|
|
675
678
|
|
|
676
679
|
for (const appDirectory of [
|
|
677
680
|
'apps/shell-super-app',
|
|
678
|
-
'
|
|
679
|
-
'
|
|
680
|
-
'
|
|
681
|
+
'verticals/commerce',
|
|
682
|
+
'verticals/identity',
|
|
683
|
+
'verticals/design-system',
|
|
681
684
|
]) {
|
|
682
685
|
if (tailwindEnabled) {
|
|
683
686
|
assertExists(`${appDirectory}/postcss.config.mjs`);
|
|
@@ -697,9 +700,9 @@ for (const appDirectory of [
|
|
|
697
700
|
|
|
698
701
|
for (const configPath of [
|
|
699
702
|
'apps/shell-super-app/modern.config.ts',
|
|
700
|
-
'
|
|
701
|
-
'
|
|
702
|
-
'
|
|
703
|
+
'verticals/commerce/modern.config.ts',
|
|
704
|
+
'verticals/identity/modern.config.ts',
|
|
705
|
+
'verticals/design-system/modern.config.ts',
|
|
703
706
|
]) {
|
|
704
707
|
const config = readText(configPath);
|
|
705
708
|
assert(config.includes('presetUltramodern('), `${configPath} must use presetUltramodern`);
|
|
@@ -748,16 +751,16 @@ assert(
|
|
|
748
751
|
'Shell MF config must share react-dom/client explicitly',
|
|
749
752
|
);
|
|
750
753
|
assert(
|
|
751
|
-
shellMf.includes('
|
|
752
|
-
'Shell must reference commerce
|
|
754
|
+
shellMf.includes('verticalCommerce@http://localhost:3021/mf-manifest.json'),
|
|
755
|
+
'Shell must reference commerce vertical',
|
|
753
756
|
);
|
|
754
757
|
assert(
|
|
755
|
-
shellMf.includes('
|
|
756
|
-
'Shell must reference identity
|
|
758
|
+
shellMf.includes('verticalIdentity@http://localhost:3022/mf-manifest.json'),
|
|
759
|
+
'Shell must reference identity vertical',
|
|
757
760
|
);
|
|
758
761
|
assert(
|
|
759
|
-
shellMf.includes('
|
|
760
|
-
'Shell must reference design-system
|
|
762
|
+
shellMf.includes('verticalDesignSystem@http://localhost:3023/mf-manifest.json'),
|
|
763
|
+
'Shell must reference design-system vertical',
|
|
761
764
|
);
|
|
762
765
|
|
|
763
766
|
const shellPackage = readJson('apps/shell-super-app/package.json');
|
|
@@ -813,14 +816,14 @@ for (const vertical of fullStackVerticals) {
|
|
|
813
816
|
);
|
|
814
817
|
}
|
|
815
818
|
|
|
816
|
-
const designMf = readText('
|
|
817
|
-
assert(designMf.includes("name: '
|
|
819
|
+
const designMf = readText('verticals/design-system/module-federation.config.ts');
|
|
820
|
+
assert(designMf.includes("name: 'verticalDesignSystem'"), 'Design-system federated MF name is missing');
|
|
818
821
|
assert(
|
|
819
822
|
designMf.includes("'react-dom/client'"),
|
|
820
|
-
'Design-system
|
|
823
|
+
'Design-system federated MF config must share react-dom/client explicitly',
|
|
821
824
|
);
|
|
822
|
-
assert(designMf.includes("'./Button'"), 'Design-system
|
|
823
|
-
assert(designMf.includes("'./tokens'"), 'Design-system
|
|
825
|
+
assert(designMf.includes("'./Button'"), 'Design-system vertical must expose Button');
|
|
826
|
+
assert(designMf.includes("'./tokens'"), 'Design-system vertical must expose tokens');
|
|
824
827
|
const sharedEffectApi = readText('packages/shared-effect-api/src/index.ts');
|
|
825
828
|
assert(
|
|
826
829
|
!sharedEffectApi.includes('recommendationsEffectApi') &&
|
|
@@ -832,10 +835,10 @@ assert(
|
|
|
832
835
|
const topology = readJson('topology/reference-topology.json');
|
|
833
836
|
assert(topology.preset === 'presetUltramodern', 'Topology must reference presetUltramodern');
|
|
834
837
|
assert(topology.shell?.id === 'shell-super-app', 'Topology shell id is incorrect');
|
|
835
|
-
assert(topology.shell?.
|
|
836
|
-
assert(topology.
|
|
838
|
+
assert(topology.shell?.verticalRefs?.length === 3, 'Topology shell must reference three verticals');
|
|
839
|
+
assert(topology.verticals?.length === 3, 'Topology must contain three verticals');
|
|
837
840
|
for (const vertical of fullStackVerticals) {
|
|
838
|
-
const topologyEntry = topology.
|
|
841
|
+
const topologyEntry = topology.verticals.find((vertical) => vertical.id === vertical.id);
|
|
839
842
|
assert(topologyEntry?.kind === 'vertical', `${vertical.id} must be a vertical topology entry`);
|
|
840
843
|
assert(
|
|
841
844
|
topologyEntry?.moduleFederation?.manifestUrl?.includes('/mf-manifest.json') &&
|
|
@@ -849,21 +852,21 @@ for (const vertical of fullStackVerticals) {
|
|
|
849
852
|
);
|
|
850
853
|
}
|
|
851
854
|
assert(
|
|
852
|
-
topology.
|
|
853
|
-
(
|
|
855
|
+
topology.verticals.some(
|
|
856
|
+
(vertical) => vertical.id === 'design-system' && vertical.kind === 'vertical',
|
|
854
857
|
),
|
|
855
|
-
'Topology must contain the horizontal design-system
|
|
858
|
+
'Topology must contain the horizontal design-system vertical',
|
|
856
859
|
);
|
|
857
860
|
assert(
|
|
858
|
-
(
|
|
859
|
-
'
|
|
861
|
+
!('effectServices' in topology),
|
|
862
|
+
'Topology must not expose effectServices; vertical APIs are owned by vertical packages',
|
|
860
863
|
);
|
|
861
864
|
assert(topology.sharedPackages?.length === 3, 'Topology must contain shared package placeholders');
|
|
862
865
|
|
|
863
866
|
const ownership = readJson('topology/ownership.json');
|
|
864
867
|
assert(
|
|
865
868
|
ownership.owners?.some(
|
|
866
|
-
(owner) => owner.id === '
|
|
869
|
+
(owner) => owner.id === 'commerce' && owner.ownership?.team === 'commerce-experience',
|
|
867
870
|
),
|
|
868
871
|
'Ownership metadata must retain commerce owner',
|
|
869
872
|
);
|
|
@@ -917,7 +920,7 @@ assert(
|
|
|
917
920
|
'Template manifest must list every pinned private agent skill entry',
|
|
918
921
|
);
|
|
919
922
|
assert(
|
|
920
|
-
manifest.validation?.expectedCommands?.includes('
|
|
923
|
+
manifest.validation?.expectedCommands?.includes('pnpm run ultramodern:check'),
|
|
921
924
|
'Template manifest must document the validation command',
|
|
922
925
|
);
|
|
923
926
|
assert(
|