@bleedingdev/modern-js-create 3.5.0-ultramodern.2 → 3.5.0-ultramodern.21
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 +22 -15
- package/dist/cjs/ultramodern-tooling/commands.cjs +393 -3
- package/dist/cjs/ultramodern-workspace/app-files.cjs +8 -11
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +13 -6
- package/dist/cjs/ultramodern-workspace/package-json.cjs +15 -8
- package/dist/cjs/ultramodern-workspace/versions.cjs +7 -2
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +2 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +2 -0
- package/dist/esm/ultramodern-tooling/commands.js +393 -3
- package/dist/esm/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm/ultramodern-workspace/module-federation.js +13 -6
- package/dist/esm/ultramodern-workspace/package-json.js +5 -8
- package/dist/esm/ultramodern-workspace/versions.js +5 -3
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +3 -1
- package/dist/esm/ultramodern-workspace/write-workspace.js +3 -1
- package/dist/esm-node/ultramodern-tooling/commands.js +393 -3
- package/dist/esm-node/ultramodern-workspace/app-files.js +8 -11
- package/dist/esm-node/ultramodern-workspace/module-federation.js +13 -6
- package/dist/esm-node/ultramodern-workspace/package-json.js +5 -8
- package/dist/esm-node/ultramodern-workspace/versions.js +5 -3
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +3 -1
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +3 -1
- package/dist/types/ultramodern-workspace/versions.d.ts +4 -2
- package/package.json +3 -3
- package/template-workspace/.gitignore.handlebars +3 -0
- package/template-workspace/README.md.handlebars +19 -13
- package/template-workspace/patches/@module-federation__bridge-react@2.6.0.patch +140 -0
- package/template-workspace/patches/@module-federation__modern-js-v3@2.6.0.patch +57 -0
- package/template-workspace/patches/drizzle-orm-ts7-strict-declarations.patch +452 -0
- package/template-workspace/patches/effect-schema-error-type-id.patch +18 -0
- package/template-workspace/pnpm-workspace.yaml.handlebars +9 -0
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +95 -5
|
@@ -486,7 +486,7 @@ const createAppConfigContract = app => ({
|
|
|
486
486
|
'zephyrRspackPlugin',
|
|
487
487
|
],
|
|
488
488
|
dev: {
|
|
489
|
-
assetPrefix: '/',
|
|
489
|
+
assetPrefix: app.kind === 'shell' ? '/' : 'app-public-origin',
|
|
490
490
|
},
|
|
491
491
|
output: {
|
|
492
492
|
assetPrefix: {
|
|
@@ -1116,6 +1116,7 @@ const assertProjectReferenceEmitConfig = (tsConfig, packagePath) => {
|
|
|
1116
1116
|
);
|
|
1117
1117
|
};
|
|
1118
1118
|
const assertTsConfigReferenceGraph = () => {
|
|
1119
|
+
const baseTsConfig = readJson('tsconfig.base.json');
|
|
1119
1120
|
const rootTsConfig = readJson('tsconfig.json');
|
|
1120
1121
|
const shellTsConfig = readJson('apps/shell-super-app/tsconfig.json');
|
|
1121
1122
|
const shellMfTypesTsConfig = readJson(
|
|
@@ -1151,6 +1152,13 @@ const assertTsConfigReferenceGraph = () => {
|
|
|
1151
1152
|
'apps/shell-super-app/tsconfig.json references',
|
|
1152
1153
|
'restore the generated shell project-reference graph',
|
|
1153
1154
|
);
|
|
1155
|
+
assert(baseTsConfig.compilerOptions?.skipLibCheck !== true, 'tsconfig.base.json must not use skipLibCheck');
|
|
1156
|
+
assertSameJson(
|
|
1157
|
+
shellTsConfig.include ?? [],
|
|
1158
|
+
['src', 'locales/**/*.json', 'package.json', 'shared'],
|
|
1159
|
+
'apps/shell-super-app/tsconfig.json include',
|
|
1160
|
+
'restore the generated shell typecheck boundary',
|
|
1161
|
+
);
|
|
1154
1162
|
assertProjectReferenceEmitConfig(
|
|
1155
1163
|
shellTsConfig,
|
|
1156
1164
|
'apps/shell-super-app',
|
|
@@ -1158,7 +1166,7 @@ const assertTsConfigReferenceGraph = () => {
|
|
|
1158
1166
|
assertSameJson(
|
|
1159
1167
|
shellMfTypesTsConfig,
|
|
1160
1168
|
{
|
|
1161
|
-
extends: '
|
|
1169
|
+
extends: '../../tsconfig.base.json',
|
|
1162
1170
|
include: ['src/modern-app-env.d.ts'],
|
|
1163
1171
|
},
|
|
1164
1172
|
'apps/shell-super-app/tsconfig.mf-types.json',
|
|
@@ -1191,11 +1199,17 @@ const assertTsConfigReferenceGraph = () => {
|
|
|
1191
1199
|
`${vertical.path}/tsconfig.json references`,
|
|
1192
1200
|
'restore the generated MicroVertical project-reference graph',
|
|
1193
1201
|
);
|
|
1202
|
+
assertSameJson(
|
|
1203
|
+
verticalTsConfig.include ?? [],
|
|
1204
|
+
['src', 'locales/**/*.json', 'package.json', 'shared', 'api'],
|
|
1205
|
+
`${vertical.path}/tsconfig.json include`,
|
|
1206
|
+
'restore the generated MicroVertical typecheck boundary',
|
|
1207
|
+
);
|
|
1194
1208
|
assertProjectReferenceEmitConfig(verticalTsConfig, vertical.path);
|
|
1195
1209
|
assertSameJson(
|
|
1196
1210
|
verticalMfTypesTsConfig,
|
|
1197
1211
|
{
|
|
1198
|
-
extends: '
|
|
1212
|
+
extends: '../../tsconfig.base.json',
|
|
1199
1213
|
include: [
|
|
1200
1214
|
'src/federation-entry.tsx',
|
|
1201
1215
|
...vertical.componentPaths.map(componentPath =>
|
|
@@ -1349,6 +1363,33 @@ const extractAssetPrefixExpression = modernConfig => {
|
|
|
1349
1363
|
assert(match?.groups?.expression, 'modern.config.ts must assign assetPrefix');
|
|
1350
1364
|
return match.groups.expression;
|
|
1351
1365
|
};
|
|
1366
|
+
const assertTargetIsolatedBuildArtifacts = (appId, modernConfig) => {
|
|
1367
|
+
assert(
|
|
1368
|
+
modernConfig.includes("const buildTarget = cloudflareDeployEnabled ? 'cloudflare' : 'web';") &&
|
|
1369
|
+
modernConfig.includes("const buildOutputRoot = cloudflareDeployEnabled ? 'dist-cloudflare' : 'dist';") &&
|
|
1370
|
+
modernConfig.includes('const buildTempDirectory = `node_modules/.modern-js-${appId}-${buildTarget}`;') &&
|
|
1371
|
+
modernConfig.includes('const buildCacheDirectory = `node_modules/.cache/rspack-${appId}-${buildTarget}`;') &&
|
|
1372
|
+
modernConfig.includes('root: buildOutputRoot,') &&
|
|
1373
|
+
modernConfig.includes('tempDir: buildTempDirectory,') &&
|
|
1374
|
+
modernConfig.includes('cacheDigest: [appId, buildTarget],') &&
|
|
1375
|
+
modernConfig.includes('cacheDirectory: buildCacheDirectory,'),
|
|
1376
|
+
`${appId} must isolate build output, Modern temp files, and Rspack cache by app and build target`,
|
|
1377
|
+
);
|
|
1378
|
+
};
|
|
1379
|
+
const assertCloudflareBuildSkipsDeployRebuild = (appId, packageJson) => {
|
|
1380
|
+
assert(
|
|
1381
|
+
packageJson.scripts?.['cloudflare:build']?.includes(
|
|
1382
|
+
'ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build',
|
|
1383
|
+
),
|
|
1384
|
+
`${appId} cloudflare:build must deploy with --skip-build after the explicit Cloudflare build`,
|
|
1385
|
+
);
|
|
1386
|
+
assert(
|
|
1387
|
+
!packageJson.scripts?.['cloudflare:build']?.includes(
|
|
1388
|
+
'--target dist && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy',
|
|
1389
|
+
),
|
|
1390
|
+
`${appId} cloudflare:build must not write public-surface assets into the normal web dist before deploy`,
|
|
1391
|
+
);
|
|
1392
|
+
};
|
|
1352
1393
|
const stripYamlInlineComment = value => {
|
|
1353
1394
|
let quote = undefined;
|
|
1354
1395
|
for (let index = 0; index < value.length; index += 1) {
|
|
@@ -1462,6 +1503,9 @@ const requiredPaths = [
|
|
|
1462
1503
|
'.gitignore',
|
|
1463
1504
|
'package.json',
|
|
1464
1505
|
'pnpm-workspace.yaml',
|
|
1506
|
+
'patches/@module-federation__modern-js-v3@{{moduleFederationVersion}}.patch',
|
|
1507
|
+
'patches/@module-federation__bridge-react@{{moduleFederationVersion}}.patch',
|
|
1508
|
+
'patches/effect-schema-error-type-id.patch',
|
|
1465
1509
|
'tsconfig.json',
|
|
1466
1510
|
'tsconfig.base.json',
|
|
1467
1511
|
'oxlint.config.ts',
|
|
@@ -1537,6 +1581,33 @@ for (const vertical of fullStackVerticals) {
|
|
|
1537
1581
|
for (const requiredPath of requiredPaths) {
|
|
1538
1582
|
assertExists(requiredPath);
|
|
1539
1583
|
}
|
|
1584
|
+
const pnpmWorkspace = readText('pnpm-workspace.yaml');
|
|
1585
|
+
assert(
|
|
1586
|
+
pnpmWorkspace.includes("'@effect/opentelemetry': {{effectVersion}}"),
|
|
1587
|
+
'pnpm-workspace.yaml must override @effect/opentelemetry to the generated Effect cohort',
|
|
1588
|
+
);
|
|
1589
|
+
assert(
|
|
1590
|
+
pnpmWorkspace.includes('effect: {{effectVersion}}'),
|
|
1591
|
+
'pnpm-workspace.yaml must override effect to the generated Effect cohort',
|
|
1592
|
+
);
|
|
1593
|
+
assert(
|
|
1594
|
+
pnpmWorkspace.includes(
|
|
1595
|
+
"'@module-federation/modern-js-v3@{{moduleFederationVersion}}': patches/@module-federation__modern-js-v3@{{moduleFederationVersion}}.patch",
|
|
1596
|
+
),
|
|
1597
|
+
'pnpm-workspace.yaml must patch the generated Module Federation Modern.js integration cohort',
|
|
1598
|
+
);
|
|
1599
|
+
assert(
|
|
1600
|
+
pnpmWorkspace.includes(
|
|
1601
|
+
"'@module-federation/bridge-react@{{moduleFederationVersion}}': patches/@module-federation__bridge-react@{{moduleFederationVersion}}.patch",
|
|
1602
|
+
),
|
|
1603
|
+
'pnpm-workspace.yaml must patch the generated Module Federation React bridge cohort',
|
|
1604
|
+
);
|
|
1605
|
+
assert(
|
|
1606
|
+
pnpmWorkspace.includes(
|
|
1607
|
+
"'effect@{{effectVersion}}': patches/effect-schema-error-type-id.patch",
|
|
1608
|
+
),
|
|
1609
|
+
'pnpm-workspace.yaml must patch the generated Effect declaration cohort',
|
|
1610
|
+
);
|
|
1540
1611
|
for (const oldRemotePath of oldRemotePaths) {
|
|
1541
1612
|
assertNotExists(oldRemotePath);
|
|
1542
1613
|
}
|
|
@@ -1751,8 +1822,17 @@ assert(JSON.stringify(generatedContract.performanceReadiness?.signals?.map(signa
|
|
|
1751
1822
|
|
|
1752
1823
|
const shellModernConfig = readText('apps/shell-super-app/modern.config.ts');
|
|
1753
1824
|
const shellModuleFederationConfig = readText('apps/shell-super-app/module-federation.config.ts');
|
|
1825
|
+
const shellModernAppEnv = readText('apps/shell-super-app/src/modern-app-env.d.ts');
|
|
1826
|
+
const gitignore = readText('.gitignore');
|
|
1754
1827
|
const shellRouteHead = readText('apps/shell-super-app/src/routes/ultramodern-route-head.tsx');
|
|
1755
1828
|
const shellRouteMetadata = readText('apps/shell-super-app/src/routes/ultramodern-route-metadata.ts');
|
|
1829
|
+
assert(/^\.mf\/$/mu.test(gitignore), 'Generated .gitignore must ignore root Module Federation diagnostics');
|
|
1830
|
+
assert(/^\*\*\/\.mf\/$/mu.test(gitignore), 'Generated .gitignore must ignore per-app Module Federation diagnostics');
|
|
1831
|
+
assert(/^dist-cloudflare\/$/mu.test(gitignore), 'Generated .gitignore must ignore Cloudflare build output');
|
|
1832
|
+
assert(shellModernAppEnv.includes("import '@modern-js/app-tools/types';"), 'Shell app env must import the framework-owned app ambient type bundle through module resolution');
|
|
1833
|
+
assert(/declare global \{\s*const ULTRAMODERN_SITE_URL: string;\s*\}/u.test(shellModernAppEnv), 'Shell app env must keep generated globals explicit after importing app ambient types');
|
|
1834
|
+
assert(!shellModernAppEnv.includes("declare module '*.svg'"), 'Shell app env must not redeclare framework-owned svg asset modules');
|
|
1835
|
+
assert(!shellModernAppEnv.includes("declare module '*.css'"), 'Shell app env must not redeclare framework-owned css asset modules');
|
|
1756
1836
|
assert(shellRouteMetadata.includes('@generated by @modern-js/create'), 'Shell route metadata compatibility manifest must be marked generated');
|
|
1757
1837
|
assert(shellRouteMetadata.includes("authoring: 'colocated-route-meta'"), 'Shell route metadata manifest must advertise colocated authoring');
|
|
1758
1838
|
const expectedZephyrDependencies = Object.fromEntries(
|
|
@@ -1771,6 +1851,9 @@ assert(shellPackage.dependencies?.['@modern-js/plugin-bff'] === expectedModernPa
|
|
|
1771
1851
|
assert(shellPackage.dependencies?.['@modern-js/plugin-i18n'] === expectedModernPackageSpecifier('@modern-js/plugin-i18n'), 'Shell plugin-i18n dependency must match package source metadata');
|
|
1772
1852
|
assert(shellPackage.dependencies?.['@modern-js/plugin-tanstack'] === expectedModernPackageSpecifier('@modern-js/plugin-tanstack'), 'Shell plugin-tanstack dependency must match package source metadata');
|
|
1773
1853
|
assert(shellPackage.dependencies?.['@modern-js/runtime'] === expectedModernPackageSpecifier('@modern-js/runtime'), 'Shell runtime dependency must match package source metadata');
|
|
1854
|
+
assert(shellPackage.scripts?.['cloudflare:deploy'] === 'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS=true pnpm run cloudflare:build && wrangler deploy --config .output/wrangler.json', 'Shell must expose cloudflare:deploy');
|
|
1855
|
+
assertTargetIsolatedBuildArtifacts('shell-super-app', shellModernConfig);
|
|
1856
|
+
assertCloudflareBuildSkipsDeployRebuild('shell-super-app', shellPackage);
|
|
1774
1857
|
const shellContract = generatedContract.apps?.find(app => app.id === 'shell-super-app');
|
|
1775
1858
|
assert(shellContract?.deploy?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell Cloudflare workerName is incorrect');
|
|
1776
1859
|
assert(shellContract?.deploy?.cloudflare?.publicUrlEnv === 'ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP', 'Shell Cloudflare public URL env is incorrect');
|
|
@@ -1841,12 +1924,19 @@ for (const vertical of fullStackVerticals) {
|
|
|
1841
1924
|
const packageJson = readJson(`${vertical.path}/package.json`);
|
|
1842
1925
|
const modernConfig = readText(`${vertical.path}/modern.config.ts`);
|
|
1843
1926
|
const moduleFederationConfig = readText(`${vertical.path}/module-federation.config.ts`);
|
|
1927
|
+
const modernAppEnv = readText(`${vertical.path}/src/modern-app-env.d.ts`);
|
|
1844
1928
|
const routeHead = readText(`${vertical.path}/src/routes/ultramodern-route-head.tsx`);
|
|
1845
1929
|
const routeMetadata = readText(`${vertical.path}/src/routes/ultramodern-route-metadata.ts`);
|
|
1930
|
+
assert(modernAppEnv.includes("import '@modern-js/app-tools/types';"), `${vertical.id} app env must import the framework-owned app ambient type bundle through module resolution`);
|
|
1931
|
+
assert(/declare global \{\s*const ULTRAMODERN_SITE_URL: string;\s*\}/u.test(modernAppEnv), `${vertical.id} app env must keep generated globals explicit after importing app ambient types`);
|
|
1932
|
+
assert(!modernAppEnv.includes("declare module '*.svg'"), `${vertical.id} app env must not redeclare framework-owned svg asset modules`);
|
|
1933
|
+
assert(!modernAppEnv.includes("declare module '*.css'"), `${vertical.id} app env must not redeclare framework-owned css asset modules`);
|
|
1846
1934
|
assert(routeMetadata.includes('@generated by @modern-js/create'), `${vertical.id} route metadata compatibility manifest must be marked generated`);
|
|
1847
1935
|
assert(routeMetadata.includes("authoring: 'colocated-route-meta'"), `${vertical.id} route metadata manifest must advertise colocated authoring`);
|
|
1848
1936
|
assert(packageJson.name === vertical.packageName, `${vertical.id} package name is incorrect`);
|
|
1849
1937
|
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`);
|
|
1938
|
+
assertTargetIsolatedBuildArtifacts(vertical.id, modernConfig);
|
|
1939
|
+
assertCloudflareBuildSkipsDeployRebuild(vertical.id, packageJson);
|
|
1850
1940
|
assert(packageJson.scripts?.['cloudflare:proof']?.includes(`--app ${vertical.id}`), `${vertical.id} must expose cloudflare:proof`);
|
|
1851
1941
|
assert(packageJson.devDependencies?.['@modern-js/app-tools'] === expectedModernPackageSpecifier('@modern-js/app-tools'), `${vertical.id} app-tools dependency must match package source metadata`);
|
|
1852
1942
|
assert(packageJson.dependencies?.['@modern-js/plugin-bff'] === expectedModernPackageSpecifier('@modern-js/plugin-bff'), `${vertical.id} plugin-bff dependency must match package source metadata`);
|
|
@@ -1892,9 +1982,9 @@ for (const vertical of fullStackVerticals) {
|
|
|
1892
1982
|
assert(!verticalAssetPrefixExpression.includes('configuredSiteUrl') && !verticalAssetPrefixExpression.includes('MODERN_PUBLIC_SITE_URL'), `${vertical.id} asset prefix must not fall back to MODERN_PUBLIC_SITE_URL`);
|
|
1893
1983
|
assert(modernConfig.includes(`envValue('ULTRAMODERN_PUBLIC_URL_${vertical.id.replace(/-/g, '_').toUpperCase()}')`), `${vertical.id} asset prefix must read its per-app public URL`);
|
|
1894
1984
|
assert(modernConfig.includes('inferredCloudflareUrl'), `${vertical.id} asset prefix must support workers.dev origin inference`);
|
|
1895
|
-
assert(
|
|
1985
|
+
assert(/dev:\s*\{\s*\/\/ Remote dev manifests must publish an absolute publicPath[\s\S]*?assetPrefix,\s*\}/u.test(modernConfig), `${vertical.id} modern.config.ts must publish dev assets from its own remote origin`);
|
|
1896
1986
|
assert(modernConfig.includes('assetPrefix,'), `${vertical.id} modern.config.ts must wire output.assetPrefix to the derived asset prefix`);
|
|
1897
|
-
assert(contractEntry?.config?.dev?.assetPrefix === '
|
|
1987
|
+
assert(contractEntry?.config?.dev?.assetPrefix === 'app-public-origin', `${vertical.id} dev asset prefix must default to its app public origin`);
|
|
1898
1988
|
assert(contractEntry?.config?.output?.assetPrefix?.default === 'app-public-origin', `${vertical.id} asset prefix must default to its app public origin`);
|
|
1899
1989
|
assert(JSON.stringify(contractEntry?.config?.output?.assetPrefix?.envFallbackOrder) === JSON.stringify(['MODERN_ASSET_PREFIX', 'ULTRAMODERN_ASSET_PREFIX']), `${vertical.id} asset prefix env fallback order is incorrect`);
|
|
1900
1990
|
assert(contractEntry?.config?.output?.disableTsChecker === false, `${vertical.id} must keep the framework TypeScript checker enabled`);
|