@bleedingdev/modern-js-create 3.2.0-ultramodern.103 → 3.2.0-ultramodern.105
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 +9 -3
- package/dist/index.js +483 -144
- package/dist/types/ultramodern-package-source.d.ts +28 -0
- package/dist/types/ultramodern-workspace.d.ts +1 -2
- package/package.json +4 -4
- package/template/modern.config.ts.handlebars +8 -8
- package/template/package.json.handlebars +14 -14
- package/template/pnpm-workspace.yaml +5 -0
- package/template/scripts/check-i18n-strings.mjs +114 -2
- package/template/scripts/validate-ultramodern.mjs.handlebars +50 -42
- package/template/tests/ultramodern.contract.test.ts.handlebars +14 -8
- package/template-workspace/README.md.handlebars +12 -3
- package/template-workspace/pnpm-workspace.yaml +6 -1
- package/template-workspace/scripts/setup-agent-reference-repos.mjs +8 -6
package/dist/index.js
CHANGED
|
@@ -559,29 +559,87 @@ const localeKeys = i18n.init('en', {
|
|
|
559
559
|
zh: ZH_LOCALE,
|
|
560
560
|
en: EN_LOCALE
|
|
561
561
|
});
|
|
562
|
+
const WORKSPACE_PACKAGE_VERSION = 'workspace:*';
|
|
563
|
+
const BLEEDINGDEV_CREATE_PACKAGE = '@bleedingdev/modern-js-create';
|
|
564
|
+
const BLEEDINGDEV_PACKAGE_SCOPE = 'bleedingdev';
|
|
565
|
+
const BLEEDINGDEV_PACKAGE_NAME_PREFIX = 'modern-js-';
|
|
566
|
+
const BLEEDINGDEV_FRAMEWORK_VERSION_ENV = 'MODERN_CREATE_ULTRAMODERN_FRAMEWORK_VERSION';
|
|
567
|
+
const ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES = [
|
|
568
|
+
'@modern-js/runtime',
|
|
569
|
+
'@modern-js/app-tools',
|
|
570
|
+
'@modern-js/tsconfig',
|
|
571
|
+
'@modern-js/plugin-i18n',
|
|
572
|
+
'@modern-js/plugin-tanstack',
|
|
573
|
+
'@modern-js/plugin-bff',
|
|
574
|
+
'@modern-js/adapter-rstest'
|
|
575
|
+
];
|
|
576
|
+
const ULTRAMODERN_WORKSPACE_MODERN_PACKAGES = [
|
|
577
|
+
'@modern-js/app-tools',
|
|
578
|
+
'@modern-js/plugin-bff',
|
|
579
|
+
'@modern-js/plugin-i18n',
|
|
580
|
+
'@modern-js/plugin-tanstack',
|
|
581
|
+
'@modern-js/runtime'
|
|
582
|
+
];
|
|
583
|
+
function modernPackageVersion(packageSource) {
|
|
584
|
+
return 'install' === packageSource.strategy ? packageSource.modernPackageVersion : WORKSPACE_PACKAGE_VERSION;
|
|
585
|
+
}
|
|
586
|
+
function modernAliasPackageName(packageName, packageSource) {
|
|
587
|
+
if (!packageSource.aliasScope) return packageName;
|
|
588
|
+
const scope = packageSource.aliasScope.replace(/^@/, '');
|
|
589
|
+
const unscopedName = packageName.split('/').at(-1);
|
|
590
|
+
return `@${scope}/${packageSource.aliasPackageNamePrefix ?? ''}${unscopedName}`;
|
|
591
|
+
}
|
|
592
|
+
function modernPackageSpecifier(packageName, packageSource) {
|
|
593
|
+
if ('install' !== packageSource.strategy) return WORKSPACE_PACKAGE_VERSION;
|
|
594
|
+
if (!packageSource.aliasScope) return packageSource.modernPackageVersion;
|
|
595
|
+
return `npm:${modernAliasPackageName(packageName, packageSource)}@${packageSource.modernPackageVersion}`;
|
|
596
|
+
}
|
|
597
|
+
function modernPackageAliases(packageNames, packageSource) {
|
|
598
|
+
if (!packageSource.aliasScope) return;
|
|
599
|
+
return Object.fromEntries(packageNames.map((packageName)=>[
|
|
600
|
+
packageName,
|
|
601
|
+
modernAliasPackageName(packageName, packageSource)
|
|
602
|
+
]));
|
|
603
|
+
}
|
|
604
|
+
function createModernPackagesMetadata(packageNames, packageSource, options = {}) {
|
|
605
|
+
const includeAliases = options.includeAliases ?? Boolean(packageSource.aliasScope);
|
|
606
|
+
const aliases = includeAliases ? modernPackageAliases(packageNames, packageSource) : void 0;
|
|
607
|
+
return {
|
|
608
|
+
packages: [
|
|
609
|
+
...packageNames
|
|
610
|
+
],
|
|
611
|
+
specifier: modernPackageVersion(packageSource),
|
|
612
|
+
...packageSource.registry ? {
|
|
613
|
+
registry: packageSource.registry
|
|
614
|
+
} : {},
|
|
615
|
+
...aliases ? {
|
|
616
|
+
aliases
|
|
617
|
+
} : {}
|
|
618
|
+
};
|
|
619
|
+
}
|
|
562
620
|
const ultramodern_workspace_dirname = node_path.dirname(fileURLToPath(import.meta.url));
|
|
563
621
|
const workspaceTemplateDir = node_path.resolve(ultramodern_workspace_dirname, '..', 'template-workspace');
|
|
564
|
-
const TANSTACK_ROUTER_VERSION = '1.170.
|
|
565
|
-
const MODULE_FEDERATION_VERSION = '2.5.
|
|
622
|
+
const TANSTACK_ROUTER_VERSION = '1.170.15';
|
|
623
|
+
const MODULE_FEDERATION_VERSION = '2.5.1';
|
|
566
624
|
const ZEPHYR_RSPACK_PLUGIN_VERSION = '1.1.1';
|
|
567
625
|
const ZEPHYR_AGENT_VERSION = '1.1.1';
|
|
568
|
-
const WRANGLER_VERSION = '4.
|
|
626
|
+
const WRANGLER_VERSION = '4.98.0';
|
|
569
627
|
const CLOUDFLARE_COMPATIBILITY_DATE = '2026-06-02';
|
|
570
628
|
const TAILWIND_VERSION = '4.3.0';
|
|
571
629
|
const TAILWIND_POSTCSS_VERSION = '4.3.0';
|
|
572
|
-
const
|
|
630
|
+
const POSTCSS_VERSION = '8.5.15';
|
|
631
|
+
const EFFECT_TSGO_VERSION = '0.14.0';
|
|
573
632
|
const TYPESCRIPT_VERSION = '6.0.3';
|
|
574
|
-
const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.
|
|
575
|
-
const OXLINT_VERSION = '1.
|
|
576
|
-
const OXFMT_VERSION = '0.
|
|
577
|
-
const ULTRACITE_VERSION = '7.
|
|
633
|
+
const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260606.1';
|
|
634
|
+
const OXLINT_VERSION = '1.68.0';
|
|
635
|
+
const OXFMT_VERSION = '0.53.0';
|
|
636
|
+
const ULTRACITE_VERSION = '7.8.1';
|
|
578
637
|
const LEFTHOOK_VERSION = '^2.1.9';
|
|
579
|
-
const I18NEXT_VERSION = '26.
|
|
580
|
-
const REACT_VERSION = '^19.2.
|
|
581
|
-
const REACT_DOM_VERSION = '^19.2.
|
|
582
|
-
const REACT_ROUTER_DOM_VERSION = '7.
|
|
638
|
+
const I18NEXT_VERSION = '26.3.1';
|
|
639
|
+
const REACT_VERSION = '^19.2.7';
|
|
640
|
+
const REACT_DOM_VERSION = '^19.2.7';
|
|
641
|
+
const REACT_ROUTER_DOM_VERSION = '7.17.0';
|
|
583
642
|
const PNPM_VERSION = '11.5.0';
|
|
584
|
-
const WORKSPACE_PACKAGE_VERSION = 'workspace:*';
|
|
585
643
|
const GENERATED_CONTRACT_PATH = '.modernjs/ultramodern-generated-contract.json';
|
|
586
644
|
const RSTACK_AGENT_SKILLS_COMMIT = '61c948b42512e223bad44b83af4080eba48b2677';
|
|
587
645
|
const MODULE_FEDERATION_AGENT_SKILLS_COMMIT = '07bb5b6c43ad457609e00c081b72d4c42508ec76';
|
|
@@ -605,13 +663,6 @@ const privateAgentSkills = [
|
|
|
605
663
|
'debugger-mode'
|
|
606
664
|
];
|
|
607
665
|
const effectTsgoTypecheckCommand = "node -e \"const fs = require('node:fs'); const { execFileSync, spawnSync } = require('node:child_process'); const bin = execFileSync('effect-tsgo', ['get-exe-path'], { encoding: 'utf8' }).trim(); if (process.platform !== 'win32') fs.chmodSync(bin, 0o755); const result = spawnSync(bin, ['--noEmit', '-p', 'tsconfig.json'], { stdio: 'inherit' }); process.exit(result.status ?? 1);\"";
|
|
608
|
-
const modernPackageNames = [
|
|
609
|
-
'@modern-js/app-tools',
|
|
610
|
-
'@modern-js/plugin-bff',
|
|
611
|
-
'@modern-js/plugin-i18n',
|
|
612
|
-
'@modern-js/plugin-tanstack',
|
|
613
|
-
'@modern-js/runtime'
|
|
614
|
-
];
|
|
615
666
|
function sortJsonValue(value) {
|
|
616
667
|
if (Array.isArray(value)) return value.map(sortJsonValue);
|
|
617
668
|
if (null !== value && 'object' == typeof value) return Object.fromEntries(Object.entries(value).sort(([left], [right])=>left.localeCompare(right)).map(([key, entry])=>[
|
|
@@ -620,6 +671,10 @@ function sortJsonValue(value) {
|
|
|
620
671
|
]));
|
|
621
672
|
return value;
|
|
622
673
|
}
|
|
674
|
+
const supportedWorkspaceLanguages = [
|
|
675
|
+
'en',
|
|
676
|
+
'cs'
|
|
677
|
+
];
|
|
623
678
|
const ULTRAMODERN_WORKSPACE_FLAG = '--ultramodern-workspace';
|
|
624
679
|
const FIRST_VERTICAL_PORT = 4101;
|
|
625
680
|
const TAILWIND_PREFIX_DIGIT_WORDS = [
|
|
@@ -914,28 +969,23 @@ function relativeRootFor(packageDir) {
|
|
|
914
969
|
return normalizePath(node_path.relative(packageDir, '.') || '.');
|
|
915
970
|
}
|
|
916
971
|
function resolvePackageSource(options) {
|
|
917
|
-
const strategy = options.packageSource?.strategy ?? '
|
|
918
|
-
return {
|
|
972
|
+
const strategy = options.packageSource?.strategy ?? 'install';
|
|
973
|
+
if ('workspace' === strategy) return {
|
|
919
974
|
strategy,
|
|
920
|
-
modernPackageVersion:
|
|
975
|
+
modernPackageVersion: WORKSPACE_PACKAGE_VERSION,
|
|
921
976
|
registry: options.packageSource?.registry,
|
|
922
977
|
aliasScope: options.packageSource?.aliasScope,
|
|
923
978
|
aliasPackageNamePrefix: options.packageSource?.aliasPackageNamePrefix
|
|
924
979
|
};
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
return
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
}
|
|
935
|
-
function modernPackageSpecifier(packageName, packageSource) {
|
|
936
|
-
if ('install' !== packageSource.strategy) return WORKSPACE_PACKAGE_VERSION;
|
|
937
|
-
if (!packageSource.aliasScope) return packageSource.modernPackageVersion;
|
|
938
|
-
return `npm:${modernAliasPackageName(packageName, packageSource)}@${packageSource.modernPackageVersion}`;
|
|
980
|
+
const registry = options.packageSource?.registry;
|
|
981
|
+
const aliasScope = options.packageSource?.aliasScope ?? (registry ? void 0 : BLEEDINGDEV_PACKAGE_SCOPE);
|
|
982
|
+
return {
|
|
983
|
+
strategy,
|
|
984
|
+
modernPackageVersion: options.packageSource?.modernPackageVersion ?? options.modernVersion,
|
|
985
|
+
registry,
|
|
986
|
+
aliasScope,
|
|
987
|
+
aliasPackageNamePrefix: options.packageSource?.aliasPackageNamePrefix ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
|
|
988
|
+
};
|
|
939
989
|
}
|
|
940
990
|
function appDependencies(scope, packageSource, app, remotes = []) {
|
|
941
991
|
const dependencies = {
|
|
@@ -968,13 +1018,13 @@ function appDevDependencies(packageSource, enableTailwind) {
|
|
|
968
1018
|
'@effect/tsgo': EFFECT_TSGO_VERSION,
|
|
969
1019
|
...enableTailwind ? {
|
|
970
1020
|
'@tailwindcss/postcss': `^${TAILWIND_POSTCSS_VERSION}`,
|
|
971
|
-
postcss:
|
|
1021
|
+
postcss: `^${POSTCSS_VERSION}`,
|
|
972
1022
|
tailwindcss: `^${TAILWIND_VERSION}`
|
|
973
1023
|
} : {},
|
|
974
1024
|
"@typescript/native-preview": TYPESCRIPT_NATIVE_PREVIEW_VERSION,
|
|
975
1025
|
'@types/node': '^20',
|
|
976
|
-
'@types/react': '^19.
|
|
977
|
-
'@types/react-dom': '^19.
|
|
1026
|
+
'@types/react': '^19.2.17',
|
|
1027
|
+
'@types/react-dom': '^19.2.3',
|
|
978
1028
|
typescript: TYPESCRIPT_VERSION,
|
|
979
1029
|
'zephyr-rspack-plugin': ZEPHYR_RSPACK_PLUGIN_VERSION,
|
|
980
1030
|
wrangler: WRANGLER_VERSION
|
|
@@ -1420,7 +1470,19 @@ if (
|
|
|
1420
1470
|
export default defineConfig(
|
|
1421
1471
|
presetUltramodern(
|
|
1422
1472
|
{
|
|
1423
|
-
${bffConfig}
|
|
1473
|
+
${bffConfig} ...(cloudflareDeployEnabled
|
|
1474
|
+
? {
|
|
1475
|
+
deploy: {
|
|
1476
|
+
worker: {
|
|
1477
|
+
compatibilityDate: '${CLOUDFLARE_COMPATIBILITY_DATE}',
|
|
1478
|
+
name: cloudflareWorkerName,
|
|
1479
|
+
security: ${formatTsJsonValue(sortJsonValue(createCloudflareSecurityContract()), 16)},
|
|
1480
|
+
ssr: true,
|
|
1481
|
+
},
|
|
1482
|
+
},
|
|
1483
|
+
}
|
|
1484
|
+
: {}),
|
|
1485
|
+
html: {
|
|
1424
1486
|
outputStructure: 'flat',
|
|
1425
1487
|
},
|
|
1426
1488
|
output: {
|
|
@@ -1457,6 +1519,9 @@ ${bffConfig} html: {
|
|
|
1457
1519
|
'/mf-manifest.json',
|
|
1458
1520
|
'/mf-stats.json',
|
|
1459
1521
|
'/remoteEntry.js',
|
|
1522
|
+
'/robots.txt',
|
|
1523
|
+
'/site.webmanifest',
|
|
1524
|
+
'/sitemap.xml',
|
|
1460
1525
|
'/static',
|
|
1461
1526
|
'/zephyr-manifest.json',
|
|
1462
1527
|
],
|
|
@@ -1469,6 +1534,20 @@ ${bffConfig} html: {
|
|
|
1469
1534
|
${bffPluginEntry} moduleFederationPlugin(),
|
|
1470
1535
|
zephyrRspackPlugin(),
|
|
1471
1536
|
],
|
|
1537
|
+
server: {
|
|
1538
|
+
port,
|
|
1539
|
+
publicDir: ['./locales', './assets'],
|
|
1540
|
+
ssr: {
|
|
1541
|
+
mode: 'string',
|
|
1542
|
+
moduleFederationAppSSR: true,
|
|
1543
|
+
},
|
|
1544
|
+
},
|
|
1545
|
+
source: {
|
|
1546
|
+
globalVars: {
|
|
1547
|
+
ULTRAMODERN_SITE_URL: siteUrl,
|
|
1548
|
+
},
|
|
1549
|
+
mainEntryName: 'index',
|
|
1550
|
+
},
|
|
1472
1551
|
tools: {
|
|
1473
1552
|
autoprefixer: {
|
|
1474
1553
|
overrideBrowserslist: ['defaults'],
|
|
@@ -1485,31 +1564,6 @@ ${bffPluginEntry} moduleFederationPlugin(),
|
|
|
1485
1564
|
]);
|
|
1486
1565
|
},
|
|
1487
1566
|
},
|
|
1488
|
-
...(cloudflareDeployEnabled
|
|
1489
|
-
? {
|
|
1490
|
-
deploy: {
|
|
1491
|
-
worker: {
|
|
1492
|
-
compatibilityDate: '${CLOUDFLARE_COMPATIBILITY_DATE}',
|
|
1493
|
-
security: ${formatTsJsonValue(createCloudflareSecurityContract(), 16)},
|
|
1494
|
-
ssr: true,
|
|
1495
|
-
},
|
|
1496
|
-
},
|
|
1497
|
-
}
|
|
1498
|
-
: {}),
|
|
1499
|
-
server: {
|
|
1500
|
-
port,
|
|
1501
|
-
publicDir: ['./locales', './assets'],
|
|
1502
|
-
ssr: {
|
|
1503
|
-
mode: 'string',
|
|
1504
|
-
moduleFederationAppSSR: true,
|
|
1505
|
-
},
|
|
1506
|
-
},
|
|
1507
|
-
source: {
|
|
1508
|
-
globalVars: {
|
|
1509
|
-
ULTRAMODERN_SITE_URL: siteUrl,
|
|
1510
|
-
},
|
|
1511
|
-
mainEntryName: 'index',
|
|
1512
|
-
},
|
|
1513
1567
|
},
|
|
1514
1568
|
{
|
|
1515
1569
|
appId,
|
|
@@ -2128,15 +2182,125 @@ function createPostcssConfig() {
|
|
|
2128
2182
|
function createTailwindConfig() {
|
|
2129
2183
|
return `import type { Config } from 'tailwindcss';
|
|
2130
2184
|
|
|
2131
|
-
export default {
|
|
2132
|
-
} satisfies Config;
|
|
2185
|
+
export default {} satisfies Config;
|
|
2133
2186
|
`;
|
|
2134
2187
|
}
|
|
2135
2188
|
function createTw(prefix) {
|
|
2136
2189
|
return (classList)=>classList.split(/\s+/u).filter(Boolean).map((candidate)=>`${prefix}:${candidate.replace(/\[&&\]:/gu, '')}`).join(' ');
|
|
2137
2190
|
}
|
|
2138
|
-
|
|
2139
|
-
|
|
2191
|
+
const publicSurfaceRequiredAssetPaths = [
|
|
2192
|
+
'config/public/robots.txt'
|
|
2193
|
+
];
|
|
2194
|
+
const publicSurfaceOptionalAssetPaths = [
|
|
2195
|
+
'config/public/sitemap.xml',
|
|
2196
|
+
'config/public/site.webmanifest'
|
|
2197
|
+
];
|
|
2198
|
+
function normalisePublicPath(pathname) {
|
|
2199
|
+
const normalised = pathname.trim().replaceAll(/\/+/gu, '/').replace(/\/+$/u, '');
|
|
2200
|
+
return normalised.length > 0 && normalised.startsWith('/') ? normalised : `/${normalised}`;
|
|
2201
|
+
}
|
|
2202
|
+
function createLocalisedPublicPath(pathname, language) {
|
|
2203
|
+
const publicPath = normalisePublicPath(pathname);
|
|
2204
|
+
return '/' === publicPath ? `/${language}` : `/${language}${publicPath}`;
|
|
2205
|
+
}
|
|
2206
|
+
function isConcretePublicPath(pathname) {
|
|
2207
|
+
return !normalisePublicPath(pathname).split('/').some((segment)=>segment.startsWith(':') || segment.includes('*') || segment.startsWith('['));
|
|
2208
|
+
}
|
|
2209
|
+
function uniqueSorted(values) {
|
|
2210
|
+
return Array.from(new Set(values)).sort((left, right)=>left.localeCompare(right));
|
|
2211
|
+
}
|
|
2212
|
+
function createPublicSurfaceRouteEntries(app) {
|
|
2213
|
+
return createPublicRouteMetadata(app).map((route)=>{
|
|
2214
|
+
const localeUrlPaths = Object.fromEntries(supportedWorkspaceLanguages.map((language)=>[
|
|
2215
|
+
language,
|
|
2216
|
+
createLocalisedPublicPath(route.localisedPaths[language], language)
|
|
2217
|
+
]));
|
|
2218
|
+
if (!Object.values(localeUrlPaths).every(isConcretePublicPath)) return;
|
|
2219
|
+
return {
|
|
2220
|
+
...route,
|
|
2221
|
+
canonicalUrlPath: localeUrlPaths.en,
|
|
2222
|
+
localeUrlPaths
|
|
2223
|
+
};
|
|
2224
|
+
}).filter((route)=>void 0 !== route).sort((left, right)=>left.canonicalUrlPath.localeCompare(right.canonicalUrlPath) || left.id.localeCompare(right.id));
|
|
2225
|
+
}
|
|
2226
|
+
function createPublicSurfaceUrlPaths(app) {
|
|
2227
|
+
return uniqueSorted(createPublicSurfaceRouteEntries(app).flatMap((route)=>supportedWorkspaceLanguages.map((language)=>route.localeUrlPaths[language])));
|
|
2228
|
+
}
|
|
2229
|
+
function createPublicSurfaceOrigin(app) {
|
|
2230
|
+
return `http://localhost:${app.port}`;
|
|
2231
|
+
}
|
|
2232
|
+
function escapeXmlText(value) {
|
|
2233
|
+
return value.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');
|
|
2234
|
+
}
|
|
2235
|
+
function escapeXmlAttribute(value) {
|
|
2236
|
+
return escapeXmlText(value).replaceAll('"', '"');
|
|
2237
|
+
}
|
|
2238
|
+
function renderRobotsTxt(app) {
|
|
2239
|
+
const urlPaths = createPublicSurfaceUrlPaths(app);
|
|
2240
|
+
const lines = [
|
|
2241
|
+
'User-agent: *'
|
|
2242
|
+
];
|
|
2243
|
+
if (0 === urlPaths.length) lines.push('Disallow: /');
|
|
2244
|
+
else {
|
|
2245
|
+
for (const urlPath of urlPaths)lines.push(`Allow: ${urlPath}$`);
|
|
2246
|
+
lines.push('Disallow: /');
|
|
2247
|
+
lines.push(`Sitemap: ${createPublicSurfaceOrigin(app)}/sitemap.xml`);
|
|
2248
|
+
}
|
|
2249
|
+
return `${lines.join('\n')}\n`;
|
|
2250
|
+
}
|
|
2251
|
+
function renderSitemapXml(app) {
|
|
2252
|
+
const origin = createPublicSurfaceOrigin(app);
|
|
2253
|
+
const routes = createPublicSurfaceRouteEntries(app);
|
|
2254
|
+
const lines = [
|
|
2255
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
2256
|
+
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">'
|
|
2257
|
+
];
|
|
2258
|
+
for (const route of routes)for (const language of supportedWorkspaceLanguages){
|
|
2259
|
+
lines.push(' <url>');
|
|
2260
|
+
lines.push(` <loc>${escapeXmlText(`${origin}${route.localeUrlPaths[language]}`)}</loc>`);
|
|
2261
|
+
for (const alternateLanguage of supportedWorkspaceLanguages)lines.push(` <xhtml:link rel="alternate" hreflang="${alternateLanguage}" href="${escapeXmlAttribute(`${origin}${route.localeUrlPaths[alternateLanguage]}`)}" />`);
|
|
2262
|
+
lines.push(` <xhtml:link rel="alternate" hreflang="x-default" href="${escapeXmlAttribute(`${origin}${route.localeUrlPaths.en}`)}" />`);
|
|
2263
|
+
lines.push(' </url>');
|
|
2264
|
+
}
|
|
2265
|
+
lines.push('</urlset>');
|
|
2266
|
+
return `${lines.join('\n')}\n`;
|
|
2267
|
+
}
|
|
2268
|
+
function renderWebManifest(app) {
|
|
2269
|
+
const startUrl = createPublicSurfaceUrlPaths(app)[0];
|
|
2270
|
+
const manifest = {
|
|
2271
|
+
name: app.displayName,
|
|
2272
|
+
short_name: app.displayName,
|
|
2273
|
+
display: 'standalone',
|
|
2274
|
+
background_color: '#ffffff',
|
|
2275
|
+
theme_color: '#133225',
|
|
2276
|
+
lang: 'en',
|
|
2277
|
+
categories: [
|
|
2278
|
+
'business',
|
|
2279
|
+
'productivity'
|
|
2280
|
+
],
|
|
2281
|
+
icons: [],
|
|
2282
|
+
...startUrl ? {
|
|
2283
|
+
scope: '/',
|
|
2284
|
+
start_url: startUrl
|
|
2285
|
+
} : {}
|
|
2286
|
+
};
|
|
2287
|
+
return `${JSON.stringify(sortJsonValue(manifest), null, 2)}\n`;
|
|
2288
|
+
}
|
|
2289
|
+
function createPublicSurfaceAssets(app) {
|
|
2290
|
+
const assets = {
|
|
2291
|
+
'config/public/robots.txt': renderRobotsTxt(app)
|
|
2292
|
+
};
|
|
2293
|
+
if (createPublicSurfaceRouteEntries(app).length > 0) {
|
|
2294
|
+
assets['config/public/sitemap.xml'] = renderSitemapXml(app);
|
|
2295
|
+
assets['config/public/site.webmanifest'] = renderWebManifest(app);
|
|
2296
|
+
}
|
|
2297
|
+
return assets;
|
|
2298
|
+
}
|
|
2299
|
+
function workspaceAssetsForApp(app) {
|
|
2300
|
+
return createPublicSurfaceAssets(app);
|
|
2301
|
+
}
|
|
2302
|
+
function rewriteWorkspaceAssetsForApp(workspaceRoot, app) {
|
|
2303
|
+
for (const [relativePath, content] of Object.entries(workspaceAssetsForApp(app)))writeFileReplacing(workspaceRoot, `${app.directory}/${relativePath}`, content);
|
|
2140
2304
|
}
|
|
2141
2305
|
function createLocalizedHeadComponent() {
|
|
2142
2306
|
return `const fallbackLanguage = 'en';
|
|
@@ -3534,7 +3698,7 @@ export const ${apiExport} = HttpApi.make('${apiName}').add(
|
|
|
3534
3698
|
.add(
|
|
3535
3699
|
HttpApiEndpoint.get('list', '/effect/${stem}', {
|
|
3536
3700
|
query: {
|
|
3537
|
-
limit: Schema.optional(Schema.
|
|
3701
|
+
limit: Schema.optional(Schema.FiniteFromString),
|
|
3538
3702
|
},
|
|
3539
3703
|
success: Schema.Struct({
|
|
3540
3704
|
items: Schema.Array(${schemaExport}),
|
|
@@ -4086,19 +4250,10 @@ function createDevelopmentOverlay(remotes = []) {
|
|
|
4086
4250
|
};
|
|
4087
4251
|
}
|
|
4088
4252
|
function createPackageSourceMetadata(scope, packageSource) {
|
|
4089
|
-
const modernPackages = {
|
|
4090
|
-
packages: modernPackageNames,
|
|
4091
|
-
specifier: modernPackageVersion(packageSource)
|
|
4092
|
-
};
|
|
4093
|
-
if (packageSource.registry) modernPackages.registry = packageSource.registry;
|
|
4094
|
-
if (packageSource.aliasScope) modernPackages.aliases = Object.fromEntries(modernPackageNames.map((packageName)=>[
|
|
4095
|
-
packageName,
|
|
4096
|
-
modernAliasPackageName(packageName, packageSource)
|
|
4097
|
-
]));
|
|
4098
4253
|
return {
|
|
4099
4254
|
schemaVersion: 1,
|
|
4100
4255
|
strategy: packageSource.strategy,
|
|
4101
|
-
modernPackages,
|
|
4256
|
+
modernPackages: createModernPackagesMetadata(ULTRAMODERN_WORKSPACE_MODERN_PACKAGES, packageSource),
|
|
4102
4257
|
generatedWorkspacePackages: {
|
|
4103
4258
|
packages: sharedPackages.map((sharedPackage)=>ultramodern_workspace_packageName(scope, sharedPackage.id)),
|
|
4104
4259
|
specifier: WORKSPACE_PACKAGE_VERSION
|
|
@@ -4348,6 +4503,23 @@ function createStylingContract(scope, app, enableTailwind) {
|
|
|
4348
4503
|
federation: createAppCssFederationContract(scope, app)
|
|
4349
4504
|
};
|
|
4350
4505
|
}
|
|
4506
|
+
function createPublicSurfaceContract(app) {
|
|
4507
|
+
const files = Object.keys(createPublicSurfaceAssets(app)).sort().map((relativePath)=>relativePath.replace(/^config\/public\//u, ''));
|
|
4508
|
+
return {
|
|
4509
|
+
source: 'route-owned-public-routes',
|
|
4510
|
+
metadataExport: './src/routes/ultramodern-route-metadata',
|
|
4511
|
+
staticRoot: 'config/public',
|
|
4512
|
+
privateRoutePolicy: 'omit-from-generated-public-surface',
|
|
4513
|
+
files,
|
|
4514
|
+
omittedByDefault: [
|
|
4515
|
+
'api-catalog.json',
|
|
4516
|
+
'llms.txt',
|
|
4517
|
+
'security.txt'
|
|
4518
|
+
],
|
|
4519
|
+
publicRoutes: createPublicRouteMetadata(app),
|
|
4520
|
+
concreteUrlPaths: createPublicSurfaceUrlPaths(app)
|
|
4521
|
+
};
|
|
4522
|
+
}
|
|
4351
4523
|
function createAppGeneratedContract(scope, app, apps, enableTailwind) {
|
|
4352
4524
|
const appWithResolvedRefs = 'shell' === app.kind ? {
|
|
4353
4525
|
...app,
|
|
@@ -4416,7 +4588,8 @@ function createAppGeneratedContract(scope, app, apps, enableTailwind) {
|
|
|
4416
4588
|
privateByDefault: true,
|
|
4417
4589
|
publicnessDefault: 'private-app-screen',
|
|
4418
4590
|
generatedRouteMap: true,
|
|
4419
|
-
manualOverrides: []
|
|
4591
|
+
manualOverrides: [],
|
|
4592
|
+
publicSurface: createPublicSurfaceContract(app)
|
|
4420
4593
|
},
|
|
4421
4594
|
moduleFederation: {
|
|
4422
4595
|
name: app.mfName,
|
|
@@ -4908,6 +5081,21 @@ const expectedBuildScript = ${JSON.stringify(expectedBuildScript)};
|
|
|
4908
5081
|
const expectedCloudflareBuildScript = ${JSON.stringify(expectedCloudflareBuildScript)};
|
|
4909
5082
|
const expectedCloudflareDeployScript = ${JSON.stringify(expectedCloudflareDeployScript)};
|
|
4910
5083
|
const expectedCloudflareSecurity = ${JSON.stringify(expectedCloudflareSecurity, null, 2)};
|
|
5084
|
+
const publicSurfaceRequiredAssetPaths = ${JSON.stringify([
|
|
5085
|
+
...publicSurfaceRequiredAssetPaths
|
|
5086
|
+
], null, 2)};
|
|
5087
|
+
const publicSurfaceOptionalAssetPaths = ${JSON.stringify([
|
|
5088
|
+
...publicSurfaceOptionalAssetPaths
|
|
5089
|
+
], null, 2)};
|
|
5090
|
+
const expectedModernPackageSpecifier = packageName => {
|
|
5091
|
+
if (packageSource.strategy === 'workspace') {
|
|
5092
|
+
return 'workspace:*';
|
|
5093
|
+
}
|
|
5094
|
+
const aliases = packageSource.modernPackages?.aliases ?? {};
|
|
5095
|
+
const alias = aliases[packageName];
|
|
5096
|
+
const specifier = packageSource.modernPackages?.specifier;
|
|
5097
|
+
return typeof alias === 'string' ? \`npm:\${alias}@\${specifier}\` : specifier;
|
|
5098
|
+
};
|
|
4911
5099
|
|
|
4912
5100
|
const readText = relativePath => fs.readFileSync(path.join(root, relativePath), 'utf-8');
|
|
4913
5101
|
const readJson = relativePath => JSON.parse(readText(relativePath));
|
|
@@ -4922,6 +5110,21 @@ const assertExists = relativePath => {
|
|
|
4922
5110
|
const assertNotExists = relativePath => {
|
|
4923
5111
|
assert(!fs.existsSync(path.join(root, relativePath)), \`Unexpected \${relativePath}\`);
|
|
4924
5112
|
};
|
|
5113
|
+
const assertPublicSurfaceAssets = (appPath, publicRoutes) => {
|
|
5114
|
+
const robots = readText(\`\${appPath}/config/public/robots.txt\`);
|
|
5115
|
+
if ((publicRoutes ?? []).length === 0) {
|
|
5116
|
+
assert(robots.includes('Disallow: /'), \`\${appPath} robots.txt must disallow crawling when no public routes exist\`);
|
|
5117
|
+
for (const relativePath of publicSurfaceOptionalAssetPaths) {
|
|
5118
|
+
assertNotExists(\`\${appPath}/\${relativePath}\`);
|
|
5119
|
+
}
|
|
5120
|
+
return;
|
|
5121
|
+
}
|
|
5122
|
+
const sitemap = readText(\`\${appPath}/config/public/sitemap.xml\`);
|
|
5123
|
+
const manifest = readJson(\`\${appPath}/config/public/site.webmanifest\`);
|
|
5124
|
+
assert(!sitemap.includes('<lastmod>'), \`\${appPath} sitemap must omit build-time lastmod values\`);
|
|
5125
|
+
assert(typeof manifest.name === 'string' && manifest.name.length > 0, \`\${appPath} web manifest must include a safe app name\`);
|
|
5126
|
+
assert(typeof manifest.start_url === 'string' && manifest.start_url.startsWith('/'), \`\${appPath} web manifest start_url must be a public route path\`);
|
|
5127
|
+
};
|
|
4925
5128
|
const expectedWorkerName = packageSuffix => \`\${packageScope}-\${packageSuffix}\`.slice(0, 63);
|
|
4926
5129
|
const expectedChunkLoadingGlobal = mfName =>
|
|
4927
5130
|
\`__ULTRAMODERN_\${mfName
|
|
@@ -4998,6 +5201,9 @@ const requiredPaths = [
|
|
|
4998
5201
|
'apps/shell-super-app/src/routes/layout.tsx',
|
|
4999
5202
|
'apps/shell-super-app/src/routes/ultramodern-route-metadata.ts',
|
|
5000
5203
|
'apps/shell-super-app/src/routes/[lang]/page.tsx',
|
|
5204
|
+
...publicSurfaceRequiredAssetPaths.map(
|
|
5205
|
+
relativePath => \`apps/shell-super-app/\${relativePath}\`,
|
|
5206
|
+
),
|
|
5001
5207
|
'packages/shared-contracts/src/index.ts',
|
|
5002
5208
|
'packages/shared-design-tokens/src/index.ts',
|
|
5003
5209
|
'packages/shared-design-tokens/src/tokens.css',
|
|
@@ -5024,6 +5230,9 @@ for (const vertical of fullStackVerticals) {
|
|
|
5024
5230
|
\`\${vertical.path}/src/routes/layout.tsx\`,
|
|
5025
5231
|
\`\${vertical.path}/src/routes/ultramodern-route-metadata.ts\`,
|
|
5026
5232
|
\`\${vertical.path}/src/routes/[lang]/page.tsx\`,
|
|
5233
|
+
...publicSurfaceRequiredAssetPaths.map(
|
|
5234
|
+
relativePath => \`\${vertical.path}/\${relativePath}\`,
|
|
5235
|
+
),
|
|
5027
5236
|
...vertical.routePagePaths,
|
|
5028
5237
|
);
|
|
5029
5238
|
}
|
|
@@ -5058,6 +5267,31 @@ assert(rootPackage.modernjs?.preset === 'presetUltramodern', 'Root must declare
|
|
|
5058
5267
|
assert(rootPackage.modernjs?.packageSource?.config === './.modernjs/ultramodern-package-source.json', 'Root must point at package source metadata');
|
|
5059
5268
|
assert(rootPackage.modernjs?.packageSource?.strategy === packageSource.strategy, 'Root package source strategy must match metadata');
|
|
5060
5269
|
assert(packageSource.strategy === 'workspace' || packageSource.strategy === 'install', 'Package source strategy must be workspace or install');
|
|
5270
|
+
assert(packageSource.strategy === 'install' || packageSource.modernPackages?.specifier === 'workspace:*', 'Workspace package source must be explicitly backed by workspace:*');
|
|
5271
|
+
if (packageSource.strategy === 'install') {
|
|
5272
|
+
const installSpecifier = packageSource.modernPackages?.specifier;
|
|
5273
|
+
assert(
|
|
5274
|
+
typeof installSpecifier === 'string' &&
|
|
5275
|
+
/^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/.test(installSpecifier) &&
|
|
5276
|
+
installSpecifier.includes('ultramodern'),
|
|
5277
|
+
'Install package source must use a semver UltraModern published cohort',
|
|
5278
|
+
);
|
|
5279
|
+
const modernAliases = packageSource.modernPackages?.aliases ?? {};
|
|
5280
|
+
if (Object.keys(modernAliases).length > 0) {
|
|
5281
|
+
for (const modernPackageName of [
|
|
5282
|
+
'@modern-js/app-tools',
|
|
5283
|
+
'@modern-js/plugin-bff',
|
|
5284
|
+
'@modern-js/plugin-i18n',
|
|
5285
|
+
'@modern-js/plugin-tanstack',
|
|
5286
|
+
'@modern-js/runtime',
|
|
5287
|
+
]) {
|
|
5288
|
+
assert(
|
|
5289
|
+
/^@[^/]+\\/.+/.test(modernAliases[modernPackageName] ?? ''),
|
|
5290
|
+
\`Install package source alias for \${modernPackageName} must be a scoped npm package\`,
|
|
5291
|
+
);
|
|
5292
|
+
}
|
|
5293
|
+
}
|
|
5294
|
+
}
|
|
5061
5295
|
assert(packageSource.generatedWorkspacePackages?.specifier === 'workspace:*', 'Generated workspace packages must keep workspace:* links');
|
|
5062
5296
|
assert(
|
|
5063
5297
|
rootPackage.scripts?.build === expectedBuildScript,
|
|
@@ -5072,6 +5306,10 @@ assert(rootPackage.scripts?.['cloudflare:proof'] === 'node ./scripts/proof-cloud
|
|
|
5072
5306
|
assert(rootPackage.scripts?.['skills:install'] === 'node ./scripts/bootstrap-agent-skills.mjs', 'Root must expose skills:install');
|
|
5073
5307
|
assert(rootPackage.scripts?.['skills:check'] === 'node ./scripts/bootstrap-agent-skills.mjs --check', 'Root must expose skills:check');
|
|
5074
5308
|
assert(rootPackage.scripts?.postinstall === "oxfmt . '!repos/**' && node ./scripts/bootstrap-agent-skills.mjs && node ./scripts/setup-agent-reference-repos.mjs", 'Root postinstall must format, bootstrap agent skills, initialize git/hooks, and install reference repositories');
|
|
5309
|
+
const agentReferenceRepoSetup = readText('scripts/setup-agent-reference-repos.mjs');
|
|
5310
|
+
assert(agentReferenceRepoSetup.includes("['commit', '--no-verify', '-m', message]"), 'Agent reference repo installer commits must skip hooks during postinstall');
|
|
5311
|
+
assert(agentReferenceRepoSetup.includes("commitInstallerChanges('Initialize UltraModern workspace')"), 'Initial agent reference repo commit must use the installer commit helper');
|
|
5312
|
+
assert(agentReferenceRepoSetup.includes("commitInstallerChanges('Record agent reference repo manifest')"), 'Agent reference repo manifest commit must use the installer commit helper');
|
|
5075
5313
|
|
|
5076
5314
|
const expectedAppIds = ['shell-super-app', ...fullStackVerticals.map(vertical => vertical.id)];
|
|
5077
5315
|
const expectedCloudflareCompatibilityDate = '${CLOUDFLARE_COMPATIBILITY_DATE}';
|
|
@@ -5091,6 +5329,7 @@ assert(generatedContract.cssFederation?.sharedDesignTokens?.dedupe?.duplicateBas
|
|
|
5091
5329
|
assert(generatedContract.cssFederation?.sharedDesignTokens?.ssr?.firstPaintRequired === true, 'Shared design token CSS must be required for SSR first paint');
|
|
5092
5330
|
|
|
5093
5331
|
const shellPackage = readJson('apps/shell-super-app/package.json');
|
|
5332
|
+
const shellModernConfig = readText('apps/shell-super-app/modern.config.ts');
|
|
5094
5333
|
const expectedZephyrDependencies = Object.fromEntries(
|
|
5095
5334
|
fullStackVerticals.map(vertical => [
|
|
5096
5335
|
vertical.zephyrAlias,
|
|
@@ -5102,6 +5341,11 @@ assert(
|
|
|
5102
5341
|
JSON.stringify(expectedZephyrDependencies),
|
|
5103
5342
|
'Shell Zephyr dependencies must reference every vertical package',
|
|
5104
5343
|
);
|
|
5344
|
+
assert(shellPackage.devDependencies?.['@modern-js/app-tools'] === expectedModernPackageSpecifier('@modern-js/app-tools'), 'Shell app-tools dependency must match package source metadata');
|
|
5345
|
+
assert(shellPackage.dependencies?.['@modern-js/plugin-bff'] === expectedModernPackageSpecifier('@modern-js/plugin-bff'), 'Shell plugin-bff dependency must match package source metadata');
|
|
5346
|
+
assert(shellPackage.dependencies?.['@modern-js/plugin-i18n'] === expectedModernPackageSpecifier('@modern-js/plugin-i18n'), 'Shell plugin-i18n dependency must match package source metadata');
|
|
5347
|
+
assert(shellPackage.dependencies?.['@modern-js/plugin-tanstack'] === expectedModernPackageSpecifier('@modern-js/plugin-tanstack'), 'Shell plugin-tanstack dependency must match package source metadata');
|
|
5348
|
+
assert(shellPackage.dependencies?.['@modern-js/runtime'] === expectedModernPackageSpecifier('@modern-js/runtime'), 'Shell runtime dependency must match package source metadata');
|
|
5105
5349
|
const shellContract = generatedContract.apps?.find(app => app.id === 'shell-super-app');
|
|
5106
5350
|
assert(shellContract?.deploy?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell Cloudflare workerName is incorrect');
|
|
5107
5351
|
assert(shellContract?.deploy?.cloudflare?.publicUrlEnv === 'ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP', 'Shell Cloudflare public URL env is incorrect');
|
|
@@ -5109,6 +5353,9 @@ assert(shellContract?.deploy?.cloudflare?.compatibilityDate === expectedCloudfla
|
|
|
5109
5353
|
assert(JSON.stringify(shellContract?.deploy?.cloudflare?.compatibilityFlags) === JSON.stringify(expectedCloudflareCompatibilityFlags), 'Shell Cloudflare compatibility flags are incorrect');
|
|
5110
5354
|
assert(JSON.stringify(shellContract?.deploy?.cloudflare?.security) === JSON.stringify(expectedCloudflareSecurity), 'Shell Cloudflare security contract is incorrect');
|
|
5111
5355
|
assert(shellContract?.deploy?.worker?.compatibilityDate === expectedCloudflareCompatibilityDate, 'Shell worker compatibilityDate is incorrect');
|
|
5356
|
+
assert(shellContract?.deploy?.worker?.name === expectedWorkerName('shell-super-app'), 'Shell worker name is incorrect');
|
|
5357
|
+
assert(shellModernConfig.includes("const cloudflareWorkerName = '" + expectedWorkerName('shell-super-app') + "'"), 'Shell modern.config.ts must define the Cloudflare worker name');
|
|
5358
|
+
assert(shellModernConfig.includes('name: cloudflareWorkerName'), 'Shell modern.config.ts must wire deploy.worker.name');
|
|
5112
5359
|
assert(shellContract?.config?.rspack?.output?.uniqueName === 'shellSuperApp', 'Shell Rspack uniqueName is incorrect');
|
|
5113
5360
|
assert(shellContract?.config?.rspack?.output?.chunkLoadingGlobal === expectedChunkLoadingGlobal('shellSuperApp'), 'Shell Rspack chunkLoadingGlobal is incorrect');
|
|
5114
5361
|
assert(topology.shell?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell topology Cloudflare workerName is incorrect');
|
|
@@ -5129,6 +5376,7 @@ assert(
|
|
|
5129
5376
|
(shellContract?.routes?.owned ?? []).every(route => route.public === false && route.indexable === false && route.publicSurface === 'private-app-screen'),
|
|
5130
5377
|
'Shell owned routes must be non-indexable private app screens by default',
|
|
5131
5378
|
);
|
|
5379
|
+
assertPublicSurfaceAssets('apps/shell-super-app', shellContract?.routes?.publicRoutes ?? []);
|
|
5132
5380
|
assert(
|
|
5133
5381
|
topology.shell?.verticalRefs?.join(',') === fullStackVerticals.map(vertical => vertical.id).join(','),
|
|
5134
5382
|
'Topology shell verticalRefs must match generated verticals',
|
|
@@ -5139,10 +5387,15 @@ assert(!('effectServices' in topology), 'Default APIs must be vertical-owned, no
|
|
|
5139
5387
|
|
|
5140
5388
|
for (const vertical of fullStackVerticals) {
|
|
5141
5389
|
const packageJson = readJson(\`\${vertical.path}/package.json\`);
|
|
5390
|
+
const modernConfig = readText(\`\${vertical.path}/modern.config.ts\`);
|
|
5142
5391
|
assert(packageJson.name === vertical.packageName, \`\${vertical.id} package name is incorrect\`);
|
|
5143
5392
|
assert(packageJson.scripts?.['cloudflare:deploy'] === 'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS=true pnpm run cloudflare:build && wrangler deploy --config .output/wrangler.json', \`\${vertical.id} must expose cloudflare:deploy\`);
|
|
5144
5393
|
assert(packageJson.scripts?.['cloudflare:proof']?.includes(\`--app \${vertical.id}\`), \`\${vertical.id} must expose cloudflare:proof\`);
|
|
5145
|
-
assert(packageJson.
|
|
5394
|
+
assert(packageJson.devDependencies?.['@modern-js/app-tools'] === expectedModernPackageSpecifier('@modern-js/app-tools'), \`\${vertical.id} app-tools dependency must match package source metadata\`);
|
|
5395
|
+
assert(packageJson.dependencies?.['@modern-js/plugin-bff'] === expectedModernPackageSpecifier('@modern-js/plugin-bff'), \`\${vertical.id} plugin-bff dependency must match package source metadata\`);
|
|
5396
|
+
assert(packageJson.dependencies?.['@modern-js/plugin-i18n'] === expectedModernPackageSpecifier('@modern-js/plugin-i18n'), \`\${vertical.id} plugin-i18n dependency must match package source metadata\`);
|
|
5397
|
+
assert(packageJson.dependencies?.['@modern-js/plugin-tanstack'] === expectedModernPackageSpecifier('@modern-js/plugin-tanstack'), \`\${vertical.id} plugin-tanstack dependency must match package source metadata\`);
|
|
5398
|
+
assert(packageJson.dependencies?.['@modern-js/runtime'] === expectedModernPackageSpecifier('@modern-js/runtime'), \`\${vertical.id} runtime dependency must match package source metadata\`);
|
|
5146
5399
|
assert(packageJson.exports?.['./effect/client'] === \`./src/effect/\${vertical.stem}-client.ts\`, \`\${vertical.id} must export its Effect client\`);
|
|
5147
5400
|
assert(packageJson.exports?.['./shared/effect/api'] === './shared/effect/api.ts', \`\${vertical.id} must export its Effect API contract\`);
|
|
5148
5401
|
const expectedVerticalZephyrDependencies = Object.fromEntries(
|
|
@@ -5168,6 +5421,9 @@ for (const vertical of fullStackVerticals) {
|
|
|
5168
5421
|
assert(JSON.stringify(contractEntry?.deploy?.cloudflare?.compatibilityFlags) === JSON.stringify(expectedCloudflareCompatibilityFlags), \`\${vertical.id} Cloudflare compatibility flags are incorrect\`);
|
|
5169
5422
|
assert(JSON.stringify(contractEntry?.deploy?.cloudflare?.security) === JSON.stringify(expectedCloudflareSecurity), \`\${vertical.id} Cloudflare security contract is incorrect\`);
|
|
5170
5423
|
assert(contractEntry?.deploy?.worker?.compatibilityDate === expectedCloudflareCompatibilityDate, \`\${vertical.id} worker compatibilityDate is incorrect\`);
|
|
5424
|
+
assert(contractEntry?.deploy?.worker?.name === expectedWorkerName(vertical.id), \`\${vertical.id} worker name is incorrect\`);
|
|
5425
|
+
assert(modernConfig.includes("const cloudflareWorkerName = '" + expectedWorkerName(vertical.id) + "'"), \`\${vertical.id} modern.config.ts must define the Cloudflare worker name\`);
|
|
5426
|
+
assert(modernConfig.includes('name: cloudflareWorkerName'), \`\${vertical.id} modern.config.ts must wire deploy.worker.name\`);
|
|
5171
5427
|
assert(contractEntry?.deploy?.cloudflare?.routes?.effectReadiness === \`\${vertical.apiPrefix}/effect/\${vertical.stem}/readiness\`, \`\${vertical.id} Cloudflare proof readiness route is incorrect\`);
|
|
5172
5428
|
assert(contractEntry?.config?.rspack?.output?.uniqueName === vertical.mfName, \`\${vertical.id} Rspack uniqueName is incorrect\`);
|
|
5173
5429
|
assert(contractEntry?.config?.rspack?.output?.chunkLoadingGlobal === expectedChunkLoadingGlobal(vertical.mfName), \`\${vertical.id} Rspack chunkLoadingGlobal is incorrect\`);
|
|
@@ -5201,6 +5457,7 @@ for (const vertical of fullStackVerticals) {
|
|
|
5201
5457
|
(contractEntry?.routes?.owned ?? []).every(route => route.public === false && route.indexable === false && route.publicSurface === 'private-app-screen'),
|
|
5202
5458
|
\`\${vertical.id} owned routes must be non-indexable private app screens by default\`,
|
|
5203
5459
|
);
|
|
5460
|
+
assertPublicSurfaceAssets(vertical.path, contractEntry?.routes?.publicRoutes ?? []);
|
|
5204
5461
|
assert(contractEntry?.styling?.federation?.owner?.id === vertical.id, \`\${vertical.id} CSS federation owner is missing\`);
|
|
5205
5462
|
assert(contractEntry?.styling?.federation?.role === 'vertical-css', \`\${vertical.id} must own only vertical CSS\`);
|
|
5206
5463
|
assert(contractEntry?.styling?.federation?.rootSelector === \`[data-app-id="\${vertical.id}"]\`, \`\${vertical.id} CSS root selector is incorrect\`);
|
|
@@ -5859,6 +6116,7 @@ function rewriteShellAppFiles(workspaceRoot, scope, packageSource, enableTailwin
|
|
|
5859
6116
|
writeJsonFile(node_path.join(workspaceRoot, `${shellApp.directory}/package.json`), createAppPackage(scope, shellHost, packageSource, enableTailwind, remotes));
|
|
5860
6117
|
writeFileReplacing(workspaceRoot, `${shellApp.directory}/src/modern-app-env.d.ts`, createAppEnvDts(shellHost, remotes));
|
|
5861
6118
|
writeFileReplacing(workspaceRoot, `${shellApp.directory}/src/routes/ultramodern-route-metadata.ts`, createRouteMetadataModule(shellHost));
|
|
6119
|
+
rewriteWorkspaceAssetsForApp(workspaceRoot, shellHost);
|
|
5862
6120
|
writeFileReplacing(workspaceRoot, `${shellApp.directory}/src/modern.runtime.ts`, createAppRuntimeConfig(shellHost, scope, remotes));
|
|
5863
6121
|
writeJsonFile(node_path.join(workspaceRoot, `${shellApp.directory}/locales/en/translation.json`), createAppPublicLocaleMessages(shellHost, 'en', remotes));
|
|
5864
6122
|
writeJsonFile(node_path.join(workspaceRoot, `${shellApp.directory}/locales/en/${appI18nNamespace(shellHost)}.json`), createAppPublicLocaleMessages(shellHost, 'en', remotes));
|
|
@@ -6066,10 +6324,24 @@ const sha1Pattern = /^[0-9a-f]{40}$/;
|
|
|
6066
6324
|
const sha256Pattern = /^[0-9a-f]{64}$/;
|
|
6067
6325
|
const templateIdPattern = /^[a-z0-9][a-z0-9._-]*$/;
|
|
6068
6326
|
const packageNamePattern = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/;
|
|
6069
|
-
const src_TANSTACK_ROUTER_VERSION = '1.170.
|
|
6327
|
+
const src_TANSTACK_ROUTER_VERSION = '1.170.15';
|
|
6070
6328
|
const src_TAILWIND_VERSION = '4.3.0';
|
|
6071
6329
|
const src_TAILWIND_POSTCSS_VERSION = '4.3.0';
|
|
6072
6330
|
const src_PNPM_VERSION = '11.5.0';
|
|
6331
|
+
const src_I18NEXT_VERSION = '26.3.1';
|
|
6332
|
+
const src_REACT_VERSION = '^19.2.7';
|
|
6333
|
+
const src_REACT_DOM_VERSION = '^19.2.7';
|
|
6334
|
+
const REACT_I18NEXT_VERSION = '17.0.8';
|
|
6335
|
+
const src_EFFECT_TSGO_VERSION = '0.14.0';
|
|
6336
|
+
const src_TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260606.1';
|
|
6337
|
+
const HAPPY_DOM_VERSION = '^20.10.1';
|
|
6338
|
+
const RSTEST_CORE_VERSION = '0.10.3';
|
|
6339
|
+
const src_OXFMT_VERSION = '0.53.0';
|
|
6340
|
+
const src_OXLINT_VERSION = '1.68.0';
|
|
6341
|
+
const src_POSTCSS_VERSION = '^8.5.15';
|
|
6342
|
+
const src_ULTRACITE_VERSION = '7.8.1';
|
|
6343
|
+
const TYPES_REACT_VERSION = '^19.2.17';
|
|
6344
|
+
const TYPES_REACT_DOM_VERSION = '^19.2.3';
|
|
6073
6345
|
const requiredDeniedPaths = [
|
|
6074
6346
|
'.git/**',
|
|
6075
6347
|
'.npmrc',
|
|
@@ -6427,7 +6699,7 @@ function readCreatePackageJson() {
|
|
|
6427
6699
|
return JSON.parse(node_fs.readFileSync(createPackageJson, 'utf-8'));
|
|
6428
6700
|
}
|
|
6429
6701
|
function isBleedingDevCreatePackage(createPackage) {
|
|
6430
|
-
return
|
|
6702
|
+
return createPackage.name === BLEEDINGDEV_CREATE_PACKAGE;
|
|
6431
6703
|
}
|
|
6432
6704
|
function getBleedingDevFrameworkVersion(createPackage, fallbackVersion) {
|
|
6433
6705
|
const frameworkVersion = createPackage.ultramodern?.frameworkVersion;
|
|
@@ -6534,71 +6806,109 @@ function detectUltramodernPackageSource(args, defaultPackageVersion, createPacka
|
|
|
6534
6806
|
console.error('--ultramodern-package-source must be "workspace" or "install"');
|
|
6535
6807
|
process.exit(1);
|
|
6536
6808
|
}
|
|
6809
|
+
const packageSourceStrategy = strategy;
|
|
6810
|
+
const explicitRegistry = getOptionValue(args, [
|
|
6811
|
+
'--ultramodern-package-registry'
|
|
6812
|
+
]);
|
|
6813
|
+
const aliasScope = getOptionValue(args, [
|
|
6814
|
+
'--ultramodern-package-scope'
|
|
6815
|
+
]) ?? (bleedingDevDefaults && 'install' === packageSourceStrategy && !explicitRegistry ? BLEEDINGDEV_PACKAGE_SCOPE : void 0);
|
|
6537
6816
|
return {
|
|
6538
|
-
strategy,
|
|
6817
|
+
strategy: packageSourceStrategy,
|
|
6539
6818
|
modernPackageVersion: getOptionValue(args, [
|
|
6540
6819
|
'--ultramodern-package-version'
|
|
6541
6820
|
]) ?? defaultPackageVersion,
|
|
6542
|
-
registry:
|
|
6543
|
-
|
|
6544
|
-
]),
|
|
6545
|
-
aliasScope: getOptionValue(args, [
|
|
6546
|
-
'--ultramodern-package-scope'
|
|
6547
|
-
]) ?? (bleedingDevDefaults && 'install' === strategy ? 'bleedingdev' : void 0),
|
|
6821
|
+
registry: explicitRegistry,
|
|
6822
|
+
aliasScope,
|
|
6548
6823
|
aliasPackageNamePrefix: getOptionValue(args, [
|
|
6549
6824
|
'--ultramodern-package-name-prefix'
|
|
6550
|
-
]) ??
|
|
6825
|
+
]) ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
|
|
6551
6826
|
};
|
|
6552
6827
|
}
|
|
6553
|
-
function
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
return
|
|
6828
|
+
function hasExplicitUltramodernPackageSource(args, value) {
|
|
6829
|
+
const configuredValue = getOptionValue(args, [
|
|
6830
|
+
'--ultramodern-package-source'
|
|
6831
|
+
]);
|
|
6832
|
+
return value ? configuredValue === value : void 0 !== configuredValue;
|
|
6558
6833
|
}
|
|
6559
|
-
function
|
|
6560
|
-
|
|
6561
|
-
if (
|
|
6562
|
-
|
|
6834
|
+
function readBleedingDevFrameworkVersionFromRegistry() {
|
|
6835
|
+
const envVersion = process.env[BLEEDINGDEV_FRAMEWORK_VERSION_ENV]?.trim();
|
|
6836
|
+
if (envVersion) {
|
|
6837
|
+
if (!semverPattern.test(envVersion)) {
|
|
6838
|
+
console.error(`${BLEEDINGDEV_FRAMEWORK_VERSION_ENV} must be a valid semver version`);
|
|
6839
|
+
process.exit(1);
|
|
6840
|
+
}
|
|
6841
|
+
return envVersion;
|
|
6842
|
+
}
|
|
6843
|
+
try {
|
|
6844
|
+
const rawVersion = runSetupCommand('npm', [
|
|
6845
|
+
'view',
|
|
6846
|
+
`${BLEEDINGDEV_CREATE_PACKAGE}@latest`,
|
|
6847
|
+
'ultramodern.frameworkVersion',
|
|
6848
|
+
'--json'
|
|
6849
|
+
]).trim();
|
|
6850
|
+
const version = JSON.parse(rawVersion);
|
|
6851
|
+
if ('string' == typeof version && semverPattern.test(version)) return version;
|
|
6852
|
+
} catch {}
|
|
6853
|
+
console.error([
|
|
6854
|
+
`Could not resolve ${BLEEDINGDEV_CREATE_PACKAGE}@latest ultramodern.frameworkVersion.`,
|
|
6855
|
+
'Pass --workspace to use local workspace protocol dependencies,',
|
|
6856
|
+
'or pass --ultramodern-package-version with the exact BleedingDev framework cohort.'
|
|
6857
|
+
].join(' '));
|
|
6858
|
+
process.exit(1);
|
|
6563
6859
|
}
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6860
|
+
function resolveInstallBackedPackageSource(args, createPackage, packageSource) {
|
|
6861
|
+
const explicitVersion = getOptionValue(args, [
|
|
6862
|
+
'--ultramodern-package-version'
|
|
6863
|
+
]);
|
|
6864
|
+
const explicitRegistry = getOptionValue(args, [
|
|
6865
|
+
'--ultramodern-package-registry'
|
|
6866
|
+
]);
|
|
6867
|
+
const aliasScope = getOptionValue(args, [
|
|
6868
|
+
'--ultramodern-package-scope'
|
|
6869
|
+
]) ?? packageSource.aliasScope ?? (explicitRegistry ? void 0 : BLEEDINGDEV_PACKAGE_SCOPE);
|
|
6870
|
+
return {
|
|
6871
|
+
...packageSource,
|
|
6872
|
+
strategy: 'install',
|
|
6873
|
+
modernPackageVersion: explicitVersion ?? (isBleedingDevCreatePackage(createPackage) ? packageSource.modernPackageVersion : readBleedingDevFrameworkVersionFromRegistry()),
|
|
6874
|
+
aliasScope,
|
|
6875
|
+
aliasPackageNamePrefix: getOptionValue(args, [
|
|
6876
|
+
'--ultramodern-package-name-prefix'
|
|
6877
|
+
]) ?? packageSource.aliasPackageNamePrefix ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
|
|
6878
|
+
};
|
|
6879
|
+
}
|
|
6880
|
+
function resolveSingleAppPackageSource(args, createPackage, packageSource, useWorkspaceProtocol) {
|
|
6881
|
+
if (useWorkspaceProtocol) return {
|
|
6882
|
+
...packageSource,
|
|
6883
|
+
strategy: 'workspace',
|
|
6884
|
+
modernPackageVersion: WORKSPACE_PACKAGE_VERSION
|
|
6885
|
+
};
|
|
6886
|
+
return resolveInstallBackedPackageSource(args, createPackage, packageSource);
|
|
6887
|
+
}
|
|
6888
|
+
function resolveWorkspacePackageSource(args, createPackage, packageSource) {
|
|
6889
|
+
if (hasExplicitUltramodernPackageSource(args, 'workspace')) return {
|
|
6890
|
+
...packageSource,
|
|
6891
|
+
strategy: 'workspace',
|
|
6892
|
+
modernPackageVersion: WORKSPACE_PACKAGE_VERSION
|
|
6893
|
+
};
|
|
6894
|
+
return resolveInstallBackedPackageSource(args, createPackage, packageSource);
|
|
6895
|
+
}
|
|
6896
|
+
function createSingleAppPackageSourceEvidence(packageSource) {
|
|
6580
6897
|
return {
|
|
6581
6898
|
schemaVersion: 1,
|
|
6582
6899
|
preset: 'presetUltramodern',
|
|
6583
|
-
strategy,
|
|
6584
|
-
modernPackages: {
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
...packageSource.registry ? {
|
|
6588
|
-
registry: packageSource.registry
|
|
6589
|
-
} : {},
|
|
6590
|
-
...aliases ? {
|
|
6591
|
-
aliases
|
|
6592
|
-
} : {}
|
|
6593
|
-
}
|
|
6900
|
+
strategy: packageSource.strategy,
|
|
6901
|
+
modernPackages: createModernPackagesMetadata(ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES, packageSource, {
|
|
6902
|
+
includeAliases: 'install' === packageSource.strategy
|
|
6903
|
+
})
|
|
6594
6904
|
};
|
|
6595
6905
|
}
|
|
6596
|
-
function writeSingleAppPackageSourceEvidence(targetDir, packageSource
|
|
6906
|
+
function writeSingleAppPackageSourceEvidence(targetDir, packageSource) {
|
|
6597
6907
|
const evidencePath = node_path.join(targetDir, '.modernjs', 'ultramodern-package-source.json');
|
|
6598
6908
|
node_fs.mkdirSync(node_path.dirname(evidencePath), {
|
|
6599
6909
|
recursive: true
|
|
6600
6910
|
});
|
|
6601
|
-
node_fs.writeFileSync(evidencePath, `${JSON.stringify(createSingleAppPackageSourceEvidence(packageSource
|
|
6911
|
+
node_fs.writeFileSync(evidencePath, `${JSON.stringify(createSingleAppPackageSourceEvidence(packageSource), null, 2)}\n`);
|
|
6602
6912
|
}
|
|
6603
6913
|
function runSetupCommand(command, args, options = {}) {
|
|
6604
6914
|
return execFileSync(command, args, {
|
|
@@ -6803,12 +7113,13 @@ async function main() {
|
|
|
6803
7113
|
}
|
|
6804
7114
|
const generateWorkspace = detectUltramodernWorkspaceFlag();
|
|
6805
7115
|
if (generateWorkspace) {
|
|
7116
|
+
const packageSource = resolveWorkspacePackageSource(args, createPackage, detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage));
|
|
6806
7117
|
generateUltramodernWorkspace({
|
|
6807
7118
|
targetDir,
|
|
6808
7119
|
packageName: generatedPackageName,
|
|
6809
7120
|
modernVersion: version,
|
|
6810
7121
|
enableTailwind: detectTailwindFlag(),
|
|
6811
|
-
packageSource
|
|
7122
|
+
packageSource
|
|
6812
7123
|
});
|
|
6813
7124
|
initializeGeneratedGitRepository(targetDir);
|
|
6814
7125
|
const dim = '\x1b[2m\x1b[3m';
|
|
@@ -6829,20 +7140,34 @@ async function main() {
|
|
|
6829
7140
|
const bffRuntime = detectBffRuntime();
|
|
6830
7141
|
const enableTailwind = detectTailwindFlag();
|
|
6831
7142
|
const useWorkspaceProtocol = detectWorkspaceProtocolFlag();
|
|
6832
|
-
const packageSource = detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage);
|
|
6833
|
-
const templateManifest = createBuiltinTemplateManifest(version);
|
|
7143
|
+
const packageSource = resolveSingleAppPackageSource(args, createPackage, detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage), useWorkspaceProtocol);
|
|
7144
|
+
const templateManifest = createBuiltinTemplateManifest('install' === packageSource.strategy ? packageSource.modernPackageVersion : version);
|
|
6834
7145
|
validateTemplateManifest(templateManifest);
|
|
6835
7146
|
copyTemplate(templateDir, targetDir, {
|
|
6836
7147
|
packageName: generatedPackageName,
|
|
6837
|
-
version:
|
|
6838
|
-
runtimeVersion:
|
|
6839
|
-
appToolsVersion:
|
|
6840
|
-
adapterRstestVersion:
|
|
6841
|
-
tsconfigVersion:
|
|
6842
|
-
pluginTanstackVersion:
|
|
6843
|
-
pluginBffVersion:
|
|
6844
|
-
pluginI18nVersion:
|
|
7148
|
+
version: 'workspace' === packageSource.strategy ? WORKSPACE_PACKAGE_VERSION : packageSource.modernPackageVersion,
|
|
7149
|
+
runtimeVersion: modernPackageSpecifier('@modern-js/runtime', packageSource),
|
|
7150
|
+
appToolsVersion: modernPackageSpecifier('@modern-js/app-tools', packageSource),
|
|
7151
|
+
adapterRstestVersion: modernPackageSpecifier('@modern-js/adapter-rstest', packageSource),
|
|
7152
|
+
tsconfigVersion: modernPackageSpecifier('@modern-js/tsconfig', packageSource),
|
|
7153
|
+
pluginTanstackVersion: modernPackageSpecifier('@modern-js/plugin-tanstack', packageSource),
|
|
7154
|
+
pluginBffVersion: modernPackageSpecifier('@modern-js/plugin-bff', packageSource),
|
|
7155
|
+
pluginI18nVersion: modernPackageSpecifier('@modern-js/plugin-i18n', packageSource),
|
|
6845
7156
|
tanstackRouterVersion: src_TANSTACK_ROUTER_VERSION,
|
|
7157
|
+
i18nextVersion: src_I18NEXT_VERSION,
|
|
7158
|
+
reactVersion: src_REACT_VERSION,
|
|
7159
|
+
reactDomVersion: src_REACT_DOM_VERSION,
|
|
7160
|
+
reactI18nextVersion: REACT_I18NEXT_VERSION,
|
|
7161
|
+
effectTsgoVersion: src_EFFECT_TSGO_VERSION,
|
|
7162
|
+
typescriptNativePreviewVersion: src_TYPESCRIPT_NATIVE_PREVIEW_VERSION,
|
|
7163
|
+
rstestCoreVersion: RSTEST_CORE_VERSION,
|
|
7164
|
+
happyDomVersion: HAPPY_DOM_VERSION,
|
|
7165
|
+
oxfmtVersion: src_OXFMT_VERSION,
|
|
7166
|
+
oxlintVersion: src_OXLINT_VERSION,
|
|
7167
|
+
postcssVersion: src_POSTCSS_VERSION,
|
|
7168
|
+
ultraciteVersion: src_ULTRACITE_VERSION,
|
|
7169
|
+
typesReactVersion: TYPES_REACT_VERSION,
|
|
7170
|
+
typesReactDomVersion: TYPES_REACT_DOM_VERSION,
|
|
6846
7171
|
tailwindVersion: src_TAILWIND_VERSION,
|
|
6847
7172
|
tailwindPostcssVersion: src_TAILWIND_POSTCSS_VERSION,
|
|
6848
7173
|
pnpmVersion: src_PNPM_VERSION,
|
|
@@ -6859,7 +7184,7 @@ async function main() {
|
|
|
6859
7184
|
...packageJson.modernjs ?? {},
|
|
6860
7185
|
preset: 'presetUltramodern',
|
|
6861
7186
|
packageSource: {
|
|
6862
|
-
strategy:
|
|
7187
|
+
strategy: packageSource.strategy,
|
|
6863
7188
|
config: './.modernjs/ultramodern-package-source.json'
|
|
6864
7189
|
}
|
|
6865
7190
|
};
|
|
@@ -6894,7 +7219,7 @@ async function main() {
|
|
|
6894
7219
|
}
|
|
6895
7220
|
node_fs.writeFileSync(targetPackageJson, `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
6896
7221
|
writeTemplateManifestEvidence(targetDir, templateManifest);
|
|
6897
|
-
writeSingleAppPackageSourceEvidence(targetDir, packageSource
|
|
7222
|
+
writeSingleAppPackageSourceEvidence(targetDir, packageSource);
|
|
6898
7223
|
if (!isSubproject) initializeGeneratedGitRepository(targetDir);
|
|
6899
7224
|
const dim = '\x1b[2m\x1b[3m';
|
|
6900
7225
|
const reset = '\x1b[0m';
|
|
@@ -6948,6 +7273,20 @@ function copyTemplate(src, dest, options) {
|
|
|
6948
7273
|
pluginBffVersion: options.pluginBffVersion,
|
|
6949
7274
|
pluginI18nVersion: options.pluginI18nVersion,
|
|
6950
7275
|
tanstackRouterVersion: options.tanstackRouterVersion,
|
|
7276
|
+
i18nextVersion: options.i18nextVersion,
|
|
7277
|
+
reactVersion: options.reactVersion,
|
|
7278
|
+
reactDomVersion: options.reactDomVersion,
|
|
7279
|
+
reactI18nextVersion: options.reactI18nextVersion,
|
|
7280
|
+
effectTsgoVersion: options.effectTsgoVersion,
|
|
7281
|
+
typescriptNativePreviewVersion: options.typescriptNativePreviewVersion,
|
|
7282
|
+
rstestCoreVersion: options.rstestCoreVersion,
|
|
7283
|
+
happyDomVersion: options.happyDomVersion,
|
|
7284
|
+
oxfmtVersion: options.oxfmtVersion,
|
|
7285
|
+
oxlintVersion: options.oxlintVersion,
|
|
7286
|
+
postcssVersion: options.postcssVersion,
|
|
7287
|
+
ultraciteVersion: options.ultraciteVersion,
|
|
7288
|
+
typesReactVersion: options.typesReactVersion,
|
|
7289
|
+
typesReactDomVersion: options.typesReactDomVersion,
|
|
6951
7290
|
tailwindVersion: options.tailwindVersion,
|
|
6952
7291
|
tailwindPostcssVersion: options.tailwindPostcssVersion,
|
|
6953
7292
|
pnpmVersion: options.pnpmVersion,
|