@bleedingdev/modern-js-create 3.5.0-ultramodern.2 → 3.5.0-ultramodern.20
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 +20 -14
- package/dist/cjs/ultramodern-tooling/commands.cjs +357 -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 +5 -0
- 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 +357 -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 +3 -1
- 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 +357 -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 +3 -1
- 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 +2 -0
- 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 +8 -0
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +87 -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,25 @@ 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(
|
|
1587
|
+
"'@module-federation/modern-js-v3@{{moduleFederationVersion}}': patches/@module-federation__modern-js-v3@{{moduleFederationVersion}}.patch",
|
|
1588
|
+
),
|
|
1589
|
+
'pnpm-workspace.yaml must patch the generated Module Federation Modern.js integration cohort',
|
|
1590
|
+
);
|
|
1591
|
+
assert(
|
|
1592
|
+
pnpmWorkspace.includes(
|
|
1593
|
+
"'@module-federation/bridge-react@{{moduleFederationVersion}}': patches/@module-federation__bridge-react@{{moduleFederationVersion}}.patch",
|
|
1594
|
+
),
|
|
1595
|
+
'pnpm-workspace.yaml must patch the generated Module Federation React bridge cohort',
|
|
1596
|
+
);
|
|
1597
|
+
assert(
|
|
1598
|
+
pnpmWorkspace.includes(
|
|
1599
|
+
"'effect@{{effectVersion}}': patches/effect-schema-error-type-id.patch",
|
|
1600
|
+
),
|
|
1601
|
+
'pnpm-workspace.yaml must patch the generated Effect declaration cohort',
|
|
1602
|
+
);
|
|
1540
1603
|
for (const oldRemotePath of oldRemotePaths) {
|
|
1541
1604
|
assertNotExists(oldRemotePath);
|
|
1542
1605
|
}
|
|
@@ -1751,8 +1814,17 @@ assert(JSON.stringify(generatedContract.performanceReadiness?.signals?.map(signa
|
|
|
1751
1814
|
|
|
1752
1815
|
const shellModernConfig = readText('apps/shell-super-app/modern.config.ts');
|
|
1753
1816
|
const shellModuleFederationConfig = readText('apps/shell-super-app/module-federation.config.ts');
|
|
1817
|
+
const shellModernAppEnv = readText('apps/shell-super-app/src/modern-app-env.d.ts');
|
|
1818
|
+
const gitignore = readText('.gitignore');
|
|
1754
1819
|
const shellRouteHead = readText('apps/shell-super-app/src/routes/ultramodern-route-head.tsx');
|
|
1755
1820
|
const shellRouteMetadata = readText('apps/shell-super-app/src/routes/ultramodern-route-metadata.ts');
|
|
1821
|
+
assert(/^\.mf\/$/mu.test(gitignore), 'Generated .gitignore must ignore root Module Federation diagnostics');
|
|
1822
|
+
assert(/^\*\*\/\.mf\/$/mu.test(gitignore), 'Generated .gitignore must ignore per-app Module Federation diagnostics');
|
|
1823
|
+
assert(/^dist-cloudflare\/$/mu.test(gitignore), 'Generated .gitignore must ignore Cloudflare build output');
|
|
1824
|
+
assert(shellModernAppEnv.includes("import '@modern-js/app-tools/types';"), 'Shell app env must import the framework-owned app ambient type bundle through module resolution');
|
|
1825
|
+
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');
|
|
1826
|
+
assert(!shellModernAppEnv.includes("declare module '*.svg'"), 'Shell app env must not redeclare framework-owned svg asset modules');
|
|
1827
|
+
assert(!shellModernAppEnv.includes("declare module '*.css'"), 'Shell app env must not redeclare framework-owned css asset modules');
|
|
1756
1828
|
assert(shellRouteMetadata.includes('@generated by @modern-js/create'), 'Shell route metadata compatibility manifest must be marked generated');
|
|
1757
1829
|
assert(shellRouteMetadata.includes("authoring: 'colocated-route-meta'"), 'Shell route metadata manifest must advertise colocated authoring');
|
|
1758
1830
|
const expectedZephyrDependencies = Object.fromEntries(
|
|
@@ -1771,6 +1843,9 @@ assert(shellPackage.dependencies?.['@modern-js/plugin-bff'] === expectedModernPa
|
|
|
1771
1843
|
assert(shellPackage.dependencies?.['@modern-js/plugin-i18n'] === expectedModernPackageSpecifier('@modern-js/plugin-i18n'), 'Shell plugin-i18n dependency must match package source metadata');
|
|
1772
1844
|
assert(shellPackage.dependencies?.['@modern-js/plugin-tanstack'] === expectedModernPackageSpecifier('@modern-js/plugin-tanstack'), 'Shell plugin-tanstack dependency must match package source metadata');
|
|
1773
1845
|
assert(shellPackage.dependencies?.['@modern-js/runtime'] === expectedModernPackageSpecifier('@modern-js/runtime'), 'Shell runtime dependency must match package source metadata');
|
|
1846
|
+
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');
|
|
1847
|
+
assertTargetIsolatedBuildArtifacts('shell-super-app', shellModernConfig);
|
|
1848
|
+
assertCloudflareBuildSkipsDeployRebuild('shell-super-app', shellPackage);
|
|
1774
1849
|
const shellContract = generatedContract.apps?.find(app => app.id === 'shell-super-app');
|
|
1775
1850
|
assert(shellContract?.deploy?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell Cloudflare workerName is incorrect');
|
|
1776
1851
|
assert(shellContract?.deploy?.cloudflare?.publicUrlEnv === 'ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP', 'Shell Cloudflare public URL env is incorrect');
|
|
@@ -1841,12 +1916,19 @@ for (const vertical of fullStackVerticals) {
|
|
|
1841
1916
|
const packageJson = readJson(`${vertical.path}/package.json`);
|
|
1842
1917
|
const modernConfig = readText(`${vertical.path}/modern.config.ts`);
|
|
1843
1918
|
const moduleFederationConfig = readText(`${vertical.path}/module-federation.config.ts`);
|
|
1919
|
+
const modernAppEnv = readText(`${vertical.path}/src/modern-app-env.d.ts`);
|
|
1844
1920
|
const routeHead = readText(`${vertical.path}/src/routes/ultramodern-route-head.tsx`);
|
|
1845
1921
|
const routeMetadata = readText(`${vertical.path}/src/routes/ultramodern-route-metadata.ts`);
|
|
1922
|
+
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`);
|
|
1923
|
+
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`);
|
|
1924
|
+
assert(!modernAppEnv.includes("declare module '*.svg'"), `${vertical.id} app env must not redeclare framework-owned svg asset modules`);
|
|
1925
|
+
assert(!modernAppEnv.includes("declare module '*.css'"), `${vertical.id} app env must not redeclare framework-owned css asset modules`);
|
|
1846
1926
|
assert(routeMetadata.includes('@generated by @modern-js/create'), `${vertical.id} route metadata compatibility manifest must be marked generated`);
|
|
1847
1927
|
assert(routeMetadata.includes("authoring: 'colocated-route-meta'"), `${vertical.id} route metadata manifest must advertise colocated authoring`);
|
|
1848
1928
|
assert(packageJson.name === vertical.packageName, `${vertical.id} package name is incorrect`);
|
|
1849
1929
|
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`);
|
|
1930
|
+
assertTargetIsolatedBuildArtifacts(vertical.id, modernConfig);
|
|
1931
|
+
assertCloudflareBuildSkipsDeployRebuild(vertical.id, packageJson);
|
|
1850
1932
|
assert(packageJson.scripts?.['cloudflare:proof']?.includes(`--app ${vertical.id}`), `${vertical.id} must expose cloudflare:proof`);
|
|
1851
1933
|
assert(packageJson.devDependencies?.['@modern-js/app-tools'] === expectedModernPackageSpecifier('@modern-js/app-tools'), `${vertical.id} app-tools dependency must match package source metadata`);
|
|
1852
1934
|
assert(packageJson.dependencies?.['@modern-js/plugin-bff'] === expectedModernPackageSpecifier('@modern-js/plugin-bff'), `${vertical.id} plugin-bff dependency must match package source metadata`);
|
|
@@ -1892,9 +1974,9 @@ for (const vertical of fullStackVerticals) {
|
|
|
1892
1974
|
assert(!verticalAssetPrefixExpression.includes('configuredSiteUrl') && !verticalAssetPrefixExpression.includes('MODERN_PUBLIC_SITE_URL'), `${vertical.id} asset prefix must not fall back to MODERN_PUBLIC_SITE_URL`);
|
|
1893
1975
|
assert(modernConfig.includes(`envValue('ULTRAMODERN_PUBLIC_URL_${vertical.id.replace(/-/g, '_').toUpperCase()}')`), `${vertical.id} asset prefix must read its per-app public URL`);
|
|
1894
1976
|
assert(modernConfig.includes('inferredCloudflareUrl'), `${vertical.id} asset prefix must support workers.dev origin inference`);
|
|
1895
|
-
assert(
|
|
1977
|
+
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
1978
|
assert(modernConfig.includes('assetPrefix,'), `${vertical.id} modern.config.ts must wire output.assetPrefix to the derived asset prefix`);
|
|
1897
|
-
assert(contractEntry?.config?.dev?.assetPrefix === '
|
|
1979
|
+
assert(contractEntry?.config?.dev?.assetPrefix === 'app-public-origin', `${vertical.id} dev asset prefix must default to its app public origin`);
|
|
1898
1980
|
assert(contractEntry?.config?.output?.assetPrefix?.default === 'app-public-origin', `${vertical.id} asset prefix must default to its app public origin`);
|
|
1899
1981
|
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
1982
|
assert(contractEntry?.config?.output?.disableTsChecker === false, `${vertical.id} must keep the framework TypeScript checker enabled`);
|