@bleedingdev/modern-js-create 3.5.0-ultramodern.11 → 3.5.0-ultramodern.13
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/dist/cjs/ultramodern-tooling/commands.cjs +83 -9
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +7 -3
- package/dist/cjs/ultramodern-workspace/package-json.cjs +1 -2
- package/dist/esm/ultramodern-tooling/commands.js +83 -9
- package/dist/esm/ultramodern-workspace/module-federation.js +7 -3
- package/dist/esm/ultramodern-workspace/package-json.js +1 -2
- package/dist/esm-node/ultramodern-tooling/commands.js +83 -9
- package/dist/esm-node/ultramodern-workspace/module-federation.js +7 -3
- package/dist/esm-node/ultramodern-workspace/package-json.js +1 -2
- package/package.json +3 -3
- package/template-workspace/.gitignore.handlebars +1 -0
- package/template-workspace/pnpm-workspace.yaml.handlebars +0 -1
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +18 -6
|
@@ -54,6 +54,7 @@ const external_create_package_root_cjs_namespaceObject = require("../create-pack
|
|
|
54
54
|
const external_ultramodern_package_source_cjs_namespaceObject = require("../ultramodern-package-source.cjs");
|
|
55
55
|
const app_files_cjs_namespaceObject = require("../ultramodern-workspace/app-files.cjs");
|
|
56
56
|
const mf_validation_cjs_namespaceObject = require("../ultramodern-workspace/mf-validation.cjs");
|
|
57
|
+
const module_federation_cjs_namespaceObject = require("../ultramodern-workspace/module-federation.cjs");
|
|
57
58
|
const package_json_cjs_namespaceObject = require("../ultramodern-workspace/package-json.cjs");
|
|
58
59
|
const versions_cjs_namespaceObject = require("../ultramodern-workspace/versions.cjs");
|
|
59
60
|
const workspace_scripts_cjs_namespaceObject = require("../ultramodern-workspace/workspace-scripts.cjs");
|
|
@@ -266,9 +267,14 @@ function updateGeneratedPackageScripts(packageJson) {
|
|
|
266
267
|
if (!scripts || 'object' != typeof scripts || Array.isArray(scripts)) return false;
|
|
267
268
|
let changed = false;
|
|
268
269
|
const cloudflareBuild = scripts['cloudflare:build'];
|
|
269
|
-
if ('string' == typeof cloudflareBuild
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
if ('string' == typeof cloudflareBuild) {
|
|
271
|
+
let nextCloudflareBuild = cloudflareBuild;
|
|
272
|
+
if (nextCloudflareBuild.includes(cloudflareModernDeployCommand) && !nextCloudflareBuild.includes(cloudflareModernDeploySkipBuildCommand)) nextCloudflareBuild = nextCloudflareBuild.replace(cloudflareModernDeployCommand, cloudflareModernDeploySkipBuildCommand);
|
|
273
|
+
nextCloudflareBuild = nextCloudflareBuild.replace(/ && node \S*scripts\/generate-public-surface-assets\.m[ct]s --app [^&]+ --target dist(?= && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build)/u, '');
|
|
274
|
+
if (nextCloudflareBuild !== cloudflareBuild) {
|
|
275
|
+
scripts['cloudflare:build'] = nextCloudflareBuild;
|
|
276
|
+
changed = true;
|
|
277
|
+
}
|
|
272
278
|
}
|
|
273
279
|
const cloudflareDeploy = scripts['cloudflare:deploy'];
|
|
274
280
|
if ('string' == typeof cloudflareDeploy && cloudflareDeploy.includes(cloudflareWranglerDeployInvalidSkipBuildCommand)) {
|
|
@@ -407,6 +413,19 @@ function ensureYamlMapEntry(source, key, entryKey, value) {
|
|
|
407
413
|
changed: true
|
|
408
414
|
};
|
|
409
415
|
}
|
|
416
|
+
function removeYamlMapEntry(source, entryKey) {
|
|
417
|
+
const packageName = entryKey.includes('@') ? entryKey.slice(0, entryKey.lastIndexOf('@')) : entryKey;
|
|
418
|
+
const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
419
|
+
const currentEntryPattern = new RegExp(`^ {2}'${escapedPackageName}@[^']+': .+\\n?`, 'mu');
|
|
420
|
+
if (!currentEntryPattern.test(source)) return {
|
|
421
|
+
source,
|
|
422
|
+
changed: false
|
|
423
|
+
};
|
|
424
|
+
return {
|
|
425
|
+
source: source.replace(currentEntryPattern, ''),
|
|
426
|
+
changed: true
|
|
427
|
+
};
|
|
428
|
+
}
|
|
410
429
|
function ensureGeneratedPatchFile(workspaceRoot, relativePatchPath, sourcePatchPath) {
|
|
411
430
|
const targetPath = external_node_path_default().join(workspaceRoot, relativePatchPath);
|
|
412
431
|
const patch = external_node_fs_default().readFileSync(sourcePatchPath, 'utf-8');
|
|
@@ -417,10 +436,53 @@ function ensureGeneratedPatchFile(workspaceRoot, relativePatchPath, sourcePatchP
|
|
|
417
436
|
external_node_fs_default().writeFileSync(targetPath, patch, 'utf-8');
|
|
418
437
|
return true;
|
|
419
438
|
}
|
|
420
|
-
function
|
|
439
|
+
function removeGeneratedPatchFileIfUnchanged(workspaceRoot, relativePatchPath, sourcePatchPath) {
|
|
440
|
+
const targetPath = external_node_path_default().join(workspaceRoot, relativePatchPath);
|
|
441
|
+
if (!external_node_fs_default().existsSync(targetPath)) return false;
|
|
442
|
+
const patch = external_node_fs_default().readFileSync(sourcePatchPath, 'utf-8');
|
|
443
|
+
if (external_node_fs_default().readFileSync(targetPath, 'utf-8') !== patch) return false;
|
|
444
|
+
external_node_fs_default().rmSync(targetPath);
|
|
445
|
+
return true;
|
|
446
|
+
}
|
|
447
|
+
function workspaceUsesDependency(workspaceRoot, packageName) {
|
|
448
|
+
const packageJsonPaths = [
|
|
449
|
+
external_node_path_default().join(workspaceRoot, 'package.json')
|
|
450
|
+
];
|
|
451
|
+
for (const workspaceDir of [
|
|
452
|
+
'apps',
|
|
453
|
+
'verticals',
|
|
454
|
+
'packages'
|
|
455
|
+
]){
|
|
456
|
+
const absoluteWorkspaceDir = external_node_path_default().join(workspaceRoot, workspaceDir);
|
|
457
|
+
if (external_node_fs_default().existsSync(absoluteWorkspaceDir)) for (const entry of external_node_fs_default().readdirSync(absoluteWorkspaceDir, {
|
|
458
|
+
withFileTypes: true
|
|
459
|
+
})){
|
|
460
|
+
if (!entry.isDirectory()) continue;
|
|
461
|
+
const packageJsonPath = external_node_path_default().join(absoluteWorkspaceDir, entry.name, 'package.json');
|
|
462
|
+
if (external_node_fs_default().existsSync(packageJsonPath)) packageJsonPaths.push(packageJsonPath);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
for (const packageJsonPath of packageJsonPaths){
|
|
466
|
+
const packageJson = JSON.parse(external_node_fs_default().readFileSync(packageJsonPath, 'utf-8'));
|
|
467
|
+
for (const field of [
|
|
468
|
+
'dependencies',
|
|
469
|
+
'devDependencies',
|
|
470
|
+
'peerDependencies',
|
|
471
|
+
'optionalDependencies'
|
|
472
|
+
]){
|
|
473
|
+
const dependencies = packageJson[field];
|
|
474
|
+
if (dependencies && 'object' == typeof dependencies) {
|
|
475
|
+
if (Object.prototype.hasOwnProperty.call(dependencies, packageName)) return true;
|
|
476
|
+
for (const specifier of Object.values(dependencies))if ('string' == typeof specifier && specifier.startsWith(`npm:${packageName}@`)) return true;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
482
|
+
function ensureGeneratedDeclarationPatches(workspaceRoot, options) {
|
|
421
483
|
let changed = false;
|
|
422
484
|
changed = ensureGeneratedPatchFile(workspaceRoot, effectDeclarationPatchPath, effectDeclarationPatchSourcePath) || changed;
|
|
423
|
-
changed = ensureGeneratedPatchFile(workspaceRoot, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed;
|
|
485
|
+
changed = options.includeDrizzleOrmPatch ? ensureGeneratedPatchFile(workspaceRoot, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed : removeGeneratedPatchFileIfUnchanged(workspaceRoot, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed;
|
|
424
486
|
return changed;
|
|
425
487
|
}
|
|
426
488
|
function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
@@ -428,6 +490,7 @@ function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
|
428
490
|
if (!external_node_fs_default().existsSync(workspaceFile)) return false;
|
|
429
491
|
let source = external_node_fs_default().readFileSync(workspaceFile, 'utf-8');
|
|
430
492
|
let changed = false;
|
|
493
|
+
const usesDrizzleOrm = workspaceUsesDependency(workspaceRoot, 'drizzle-orm');
|
|
431
494
|
const replacements = [
|
|
432
495
|
[
|
|
433
496
|
/^ {4}'@effect\/vitest>effect': .+$/mu,
|
|
@@ -465,7 +528,7 @@ function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
|
465
528
|
const effectPatch = ensureYamlMapEntry(source, 'patchedDependencies', `effect@${versions_cjs_namespaceObject.EFFECT_VERSION}`, effectDeclarationPatchPath);
|
|
466
529
|
source = effectPatch.source;
|
|
467
530
|
changed = effectPatch.changed || changed;
|
|
468
|
-
const drizzleOrmPatch = ensureYamlMapEntry(source, 'patchedDependencies', `drizzle-orm@${versions_cjs_namespaceObject.DRIZZLE_ORM_VERSION}`, drizzleOrmDeclarationPatchPath);
|
|
531
|
+
const drizzleOrmPatch = usesDrizzleOrm ? ensureYamlMapEntry(source, 'patchedDependencies', `drizzle-orm@${versions_cjs_namespaceObject.DRIZZLE_ORM_VERSION}`, drizzleOrmDeclarationPatchPath) : removeYamlMapEntry(source, `drizzle-orm@${versions_cjs_namespaceObject.DRIZZLE_ORM_VERSION}`);
|
|
469
532
|
source = drizzleOrmPatch.source;
|
|
470
533
|
changed = drizzleOrmPatch.changed || changed;
|
|
471
534
|
if (changed) external_node_fs_default().writeFileSync(workspaceFile, source, 'utf-8');
|
|
@@ -514,7 +577,8 @@ function ensureGeneratedIgnoreRules(workspaceRoot) {
|
|
|
514
577
|
let changed = false;
|
|
515
578
|
for (const rule of [
|
|
516
579
|
'.mf/',
|
|
517
|
-
'**/.mf/'
|
|
580
|
+
'**/.mf/',
|
|
581
|
+
'dist-cloudflare/'
|
|
518
582
|
])if (!lines.includes(rule)) {
|
|
519
583
|
lines.push(rule);
|
|
520
584
|
changed = true;
|
|
@@ -541,6 +605,12 @@ function updateGeneratedTypeScriptSurfaces(workspaceRoot, config) {
|
|
|
541
605
|
}
|
|
542
606
|
return changed;
|
|
543
607
|
}
|
|
608
|
+
function updateGeneratedModernConfigs(workspaceRoot, config) {
|
|
609
|
+
let changed = false;
|
|
610
|
+
const apps = (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)(config);
|
|
611
|
+
for (const app of apps)changed = writeTextIfChanged(external_node_path_default().join(workspaceRoot, app.directory, 'modern.config.ts'), (0, module_federation_cjs_namespaceObject.createAppModernConfig)(config.workspace.packageScope, app)) || changed;
|
|
612
|
+
return changed;
|
|
613
|
+
}
|
|
544
614
|
function updateReferenceTopology(workspaceRoot) {
|
|
545
615
|
const topologyPath = external_node_path_default().join(workspaceRoot, 'topology/reference-topology.json');
|
|
546
616
|
if (!external_node_fs_default().existsSync(topologyPath)) return false;
|
|
@@ -614,7 +684,9 @@ and pnpm contract:check.
|
|
|
614
684
|
const packageSource = createMigrationPackageSource(args, current);
|
|
615
685
|
updateUltramodernConfig(context.workspaceRoot, packageSource);
|
|
616
686
|
updateReferenceTopology(context.workspaceRoot);
|
|
617
|
-
|
|
687
|
+
const migrated = (0, external_config_cjs_namespaceObject.readUltramodernConfig)(context.workspaceRoot);
|
|
688
|
+
updateGeneratedTypeScriptSurfaces(context.workspaceRoot, migrated);
|
|
689
|
+
updateGeneratedModernConfigs(context.workspaceRoot, migrated);
|
|
618
690
|
for (const relativePackageFile of listWorkspacePackageFiles(context.workspaceRoot)){
|
|
619
691
|
const packageFile = external_node_path_default().join(context.workspaceRoot, relativePackageFile);
|
|
620
692
|
const packageJson = readJsonFile(packageFile);
|
|
@@ -633,7 +705,9 @@ and pnpm contract:check.
|
|
|
633
705
|
else if ('package.json' === relativePackageFile) writeJsonFile(packageFile, packageJson);
|
|
634
706
|
}
|
|
635
707
|
updateGeneratedPnpmWorkspacePolicy(context.workspaceRoot);
|
|
636
|
-
ensureGeneratedDeclarationPatches(context.workspaceRoot
|
|
708
|
+
ensureGeneratedDeclarationPatches(context.workspaceRoot, {
|
|
709
|
+
includeDrizzleOrmPatch: workspaceUsesDependency(context.workspaceRoot, 'drizzle-orm')
|
|
710
|
+
});
|
|
637
711
|
if (!hasFlag(args, '--skip-install')) {
|
|
638
712
|
const status = runPnpmLockfileRefresh(context);
|
|
639
713
|
if (0 !== status) return status;
|
|
@@ -144,8 +144,10 @@ ${defaultAssetPrefixSource}
|
|
|
144
144
|
// load remoteEntry.js and exposed chunks from the remote origin, not the host.
|
|
145
145
|
const assetPrefix =
|
|
146
146
|
configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix;
|
|
147
|
-
const
|
|
148
|
-
const
|
|
147
|
+
const buildTarget = cloudflareDeployEnabled ? 'cloudflare' : 'web';
|
|
148
|
+
const buildOutputRoot = cloudflareDeployEnabled ? 'dist-cloudflare' : 'dist';
|
|
149
|
+
const buildTempDirectory = \`node_modules/.modern-js-\${appId}-\${buildTarget}\`;
|
|
150
|
+
const buildCacheDirectory = \`node_modules/.cache/rspack-\${appId}-\${buildTarget}\`;
|
|
149
151
|
|
|
150
152
|
if (
|
|
151
153
|
cloudflareDeployEnabled &&
|
|
@@ -187,13 +189,15 @@ ${bffConfig} ...(cloudflareDeployEnabled
|
|
|
187
189
|
disableTsChecker: false,
|
|
188
190
|
distPath: {
|
|
189
191
|
html: './',
|
|
192
|
+
root: buildOutputRoot,
|
|
190
193
|
},
|
|
191
194
|
polyfill: 'off',
|
|
192
195
|
splitRouteChunks: true,
|
|
196
|
+
tempDir: buildTempDirectory,
|
|
193
197
|
},
|
|
194
198
|
performance: {
|
|
195
199
|
buildCache: {
|
|
196
|
-
cacheDigest: [appId,
|
|
200
|
+
cacheDigest: [appId, buildTarget],
|
|
197
201
|
cacheDirectory: buildCacheDirectory,
|
|
198
202
|
},
|
|
199
203
|
rsdoctor: {
|
|
@@ -412,7 +412,6 @@ function createRootTsConfig(apps = []) {
|
|
|
412
412
|
}
|
|
413
413
|
function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [], bridge) {
|
|
414
414
|
const publicSurfaceBuildCommand = (0, external_public_surface_cjs_namespaceObject.createPublicSurfaceGenerationCommand)(app, 'dist');
|
|
415
|
-
const publicSurfaceCloudflareBuildCommand = (0, external_public_surface_cjs_namespaceObject.createPublicSurfaceGenerationCommand)(app, 'dist');
|
|
416
415
|
const publicSurfaceCloudflareOutputCommand = (0, external_public_surface_cjs_namespaceObject.createPublicSurfaceGenerationCommand)(app, 'cloudflare');
|
|
417
416
|
const packageExports = Object.fromEntries(Object.entries(app.exposes ?? {}).map(([expose, source])=>[
|
|
418
417
|
expose,
|
|
@@ -425,7 +424,7 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
|
|
|
425
424
|
scripts: {
|
|
426
425
|
dev: 'modern dev',
|
|
427
426
|
build: app.exposes ? `ULTRAMODERN_ZEPHYR=false modern build && ${publicSurfaceBuildCommand} && node ${(0, external_naming_cjs_namespaceObject.relativeRootFor)(app.directory)}/scripts/assert-mf-types.mts` : `ULTRAMODERN_ZEPHYR=false modern build && ${publicSurfaceBuildCommand}`,
|
|
428
|
-
'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build &&
|
|
427
|
+
'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build && ${publicSurfaceCloudflareOutputCommand}`,
|
|
429
428
|
'cloudflare:deploy': 'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS=true pnpm run cloudflare:build && wrangler deploy --config .output/wrangler.json',
|
|
430
429
|
'cloudflare:preview': 'pnpm run cloudflare:build && wrangler dev --config .output/wrangler.json',
|
|
431
430
|
'cloudflare:proof': `node ${(0, external_naming_cjs_namespaceObject.relativeRootFor)(app.directory)}/scripts/proof-cloudflare-version.mts --app ${app.id}`,
|
|
@@ -7,6 +7,7 @@ import { resolveCreatePackageRoot } from "../create-package-root.js";
|
|
|
7
7
|
import { BLEEDINGDEV_PACKAGE_NAME_PREFIX, BLEEDINGDEV_PACKAGE_SCOPE, ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES, ULTRAMODERN_WORKSPACE_MODERN_PACKAGES, WORKSPACE_PACKAGE_VERSION, modernPackageSpecifier } from "../ultramodern-package-source.js";
|
|
8
8
|
import { createAppEnvDts } from "../ultramodern-workspace/app-files.js";
|
|
9
9
|
import { validateModuleFederationTypes } from "../ultramodern-workspace/mf-validation.js";
|
|
10
|
+
import { createAppModernConfig } from "../ultramodern-workspace/module-federation.js";
|
|
10
11
|
import { createAppMfTypesTsConfig, createAppTsConfig, createSharedPackageTsConfig, createTsConfigBase } from "../ultramodern-workspace/package-json.js";
|
|
11
12
|
import { DRIZZLE_ORM_VERSION, EFFECT_TSGO_VERSION, EFFECT_VERSION, EFFECT_VITEST_VERSION, OXFMT_VERSION, OXLINT_VERSION, TYPESCRIPT_NATIVE_PREVIEW_VERSION, WRANGLER_VERSION, ZEPHYR_AGENT_VERSION, ZEPHYR_RSPACK_PLUGIN_VERSION } from "../ultramodern-workspace/versions.js";
|
|
12
13
|
import { createWorkspaceValidationScript } from "../ultramodern-workspace/workspace-scripts.js";
|
|
@@ -219,9 +220,14 @@ function updateGeneratedPackageScripts(packageJson) {
|
|
|
219
220
|
if (!scripts || 'object' != typeof scripts || Array.isArray(scripts)) return false;
|
|
220
221
|
let changed = false;
|
|
221
222
|
const cloudflareBuild = scripts['cloudflare:build'];
|
|
222
|
-
if ('string' == typeof cloudflareBuild
|
|
223
|
-
|
|
224
|
-
|
|
223
|
+
if ('string' == typeof cloudflareBuild) {
|
|
224
|
+
let nextCloudflareBuild = cloudflareBuild;
|
|
225
|
+
if (nextCloudflareBuild.includes(cloudflareModernDeployCommand) && !nextCloudflareBuild.includes(cloudflareModernDeploySkipBuildCommand)) nextCloudflareBuild = nextCloudflareBuild.replace(cloudflareModernDeployCommand, cloudflareModernDeploySkipBuildCommand);
|
|
226
|
+
nextCloudflareBuild = nextCloudflareBuild.replace(/ && node \S*scripts\/generate-public-surface-assets\.m[ct]s --app [^&]+ --target dist(?= && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build)/u, '');
|
|
227
|
+
if (nextCloudflareBuild !== cloudflareBuild) {
|
|
228
|
+
scripts['cloudflare:build'] = nextCloudflareBuild;
|
|
229
|
+
changed = true;
|
|
230
|
+
}
|
|
225
231
|
}
|
|
226
232
|
const cloudflareDeploy = scripts['cloudflare:deploy'];
|
|
227
233
|
if ('string' == typeof cloudflareDeploy && cloudflareDeploy.includes(cloudflareWranglerDeployInvalidSkipBuildCommand)) {
|
|
@@ -360,6 +366,19 @@ function ensureYamlMapEntry(source, key, entryKey, value) {
|
|
|
360
366
|
changed: true
|
|
361
367
|
};
|
|
362
368
|
}
|
|
369
|
+
function removeYamlMapEntry(source, entryKey) {
|
|
370
|
+
const packageName = entryKey.includes('@') ? entryKey.slice(0, entryKey.lastIndexOf('@')) : entryKey;
|
|
371
|
+
const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
372
|
+
const currentEntryPattern = new RegExp(`^ {2}'${escapedPackageName}@[^']+': .+\\n?`, 'mu');
|
|
373
|
+
if (!currentEntryPattern.test(source)) return {
|
|
374
|
+
source,
|
|
375
|
+
changed: false
|
|
376
|
+
};
|
|
377
|
+
return {
|
|
378
|
+
source: source.replace(currentEntryPattern, ''),
|
|
379
|
+
changed: true
|
|
380
|
+
};
|
|
381
|
+
}
|
|
363
382
|
function ensureGeneratedPatchFile(workspaceRoot, relativePatchPath, sourcePatchPath) {
|
|
364
383
|
const targetPath = node_path.join(workspaceRoot, relativePatchPath);
|
|
365
384
|
const patch = node_fs.readFileSync(sourcePatchPath, 'utf-8');
|
|
@@ -370,10 +389,53 @@ function ensureGeneratedPatchFile(workspaceRoot, relativePatchPath, sourcePatchP
|
|
|
370
389
|
node_fs.writeFileSync(targetPath, patch, 'utf-8');
|
|
371
390
|
return true;
|
|
372
391
|
}
|
|
373
|
-
function
|
|
392
|
+
function removeGeneratedPatchFileIfUnchanged(workspaceRoot, relativePatchPath, sourcePatchPath) {
|
|
393
|
+
const targetPath = node_path.join(workspaceRoot, relativePatchPath);
|
|
394
|
+
if (!node_fs.existsSync(targetPath)) return false;
|
|
395
|
+
const patch = node_fs.readFileSync(sourcePatchPath, 'utf-8');
|
|
396
|
+
if (node_fs.readFileSync(targetPath, 'utf-8') !== patch) return false;
|
|
397
|
+
node_fs.rmSync(targetPath);
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
function workspaceUsesDependency(workspaceRoot, packageName) {
|
|
401
|
+
const packageJsonPaths = [
|
|
402
|
+
node_path.join(workspaceRoot, 'package.json')
|
|
403
|
+
];
|
|
404
|
+
for (const workspaceDir of [
|
|
405
|
+
'apps',
|
|
406
|
+
'verticals',
|
|
407
|
+
'packages'
|
|
408
|
+
]){
|
|
409
|
+
const absoluteWorkspaceDir = node_path.join(workspaceRoot, workspaceDir);
|
|
410
|
+
if (node_fs.existsSync(absoluteWorkspaceDir)) for (const entry of node_fs.readdirSync(absoluteWorkspaceDir, {
|
|
411
|
+
withFileTypes: true
|
|
412
|
+
})){
|
|
413
|
+
if (!entry.isDirectory()) continue;
|
|
414
|
+
const packageJsonPath = node_path.join(absoluteWorkspaceDir, entry.name, 'package.json');
|
|
415
|
+
if (node_fs.existsSync(packageJsonPath)) packageJsonPaths.push(packageJsonPath);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
for (const packageJsonPath of packageJsonPaths){
|
|
419
|
+
const packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
420
|
+
for (const field of [
|
|
421
|
+
'dependencies',
|
|
422
|
+
'devDependencies',
|
|
423
|
+
'peerDependencies',
|
|
424
|
+
'optionalDependencies'
|
|
425
|
+
]){
|
|
426
|
+
const dependencies = packageJson[field];
|
|
427
|
+
if (dependencies && 'object' == typeof dependencies) {
|
|
428
|
+
if (Object.prototype.hasOwnProperty.call(dependencies, packageName)) return true;
|
|
429
|
+
for (const specifier of Object.values(dependencies))if ('string' == typeof specifier && specifier.startsWith(`npm:${packageName}@`)) return true;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
435
|
+
function ensureGeneratedDeclarationPatches(workspaceRoot, options) {
|
|
374
436
|
let changed = false;
|
|
375
437
|
changed = ensureGeneratedPatchFile(workspaceRoot, effectDeclarationPatchPath, effectDeclarationPatchSourcePath) || changed;
|
|
376
|
-
changed = ensureGeneratedPatchFile(workspaceRoot, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed;
|
|
438
|
+
changed = options.includeDrizzleOrmPatch ? ensureGeneratedPatchFile(workspaceRoot, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed : removeGeneratedPatchFileIfUnchanged(workspaceRoot, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed;
|
|
377
439
|
return changed;
|
|
378
440
|
}
|
|
379
441
|
function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
@@ -381,6 +443,7 @@ function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
|
381
443
|
if (!node_fs.existsSync(workspaceFile)) return false;
|
|
382
444
|
let source = node_fs.readFileSync(workspaceFile, 'utf-8');
|
|
383
445
|
let changed = false;
|
|
446
|
+
const usesDrizzleOrm = workspaceUsesDependency(workspaceRoot, 'drizzle-orm');
|
|
384
447
|
const replacements = [
|
|
385
448
|
[
|
|
386
449
|
/^ {4}'@effect\/vitest>effect': .+$/mu,
|
|
@@ -418,7 +481,7 @@ function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
|
418
481
|
const effectPatch = ensureYamlMapEntry(source, 'patchedDependencies', `effect@${EFFECT_VERSION}`, effectDeclarationPatchPath);
|
|
419
482
|
source = effectPatch.source;
|
|
420
483
|
changed = effectPatch.changed || changed;
|
|
421
|
-
const drizzleOrmPatch = ensureYamlMapEntry(source, 'patchedDependencies', `drizzle-orm@${DRIZZLE_ORM_VERSION}`, drizzleOrmDeclarationPatchPath);
|
|
484
|
+
const drizzleOrmPatch = usesDrizzleOrm ? ensureYamlMapEntry(source, 'patchedDependencies', `drizzle-orm@${DRIZZLE_ORM_VERSION}`, drizzleOrmDeclarationPatchPath) : removeYamlMapEntry(source, `drizzle-orm@${DRIZZLE_ORM_VERSION}`);
|
|
422
485
|
source = drizzleOrmPatch.source;
|
|
423
486
|
changed = drizzleOrmPatch.changed || changed;
|
|
424
487
|
if (changed) node_fs.writeFileSync(workspaceFile, source, 'utf-8');
|
|
@@ -467,7 +530,8 @@ function ensureGeneratedIgnoreRules(workspaceRoot) {
|
|
|
467
530
|
let changed = false;
|
|
468
531
|
for (const rule of [
|
|
469
532
|
'.mf/',
|
|
470
|
-
'**/.mf/'
|
|
533
|
+
'**/.mf/',
|
|
534
|
+
'dist-cloudflare/'
|
|
471
535
|
])if (!lines.includes(rule)) {
|
|
472
536
|
lines.push(rule);
|
|
473
537
|
changed = true;
|
|
@@ -494,6 +558,12 @@ function updateGeneratedTypeScriptSurfaces(workspaceRoot, config) {
|
|
|
494
558
|
}
|
|
495
559
|
return changed;
|
|
496
560
|
}
|
|
561
|
+
function updateGeneratedModernConfigs(workspaceRoot, config) {
|
|
562
|
+
let changed = false;
|
|
563
|
+
const apps = workspaceAppsFromToolingConfig(config);
|
|
564
|
+
for (const app of apps)changed = writeTextIfChanged(node_path.join(workspaceRoot, app.directory, 'modern.config.ts'), createAppModernConfig(config.workspace.packageScope, app)) || changed;
|
|
565
|
+
return changed;
|
|
566
|
+
}
|
|
497
567
|
function updateReferenceTopology(workspaceRoot) {
|
|
498
568
|
const topologyPath = node_path.join(workspaceRoot, 'topology/reference-topology.json');
|
|
499
569
|
if (!node_fs.existsSync(topologyPath)) return false;
|
|
@@ -567,7 +637,9 @@ and pnpm contract:check.
|
|
|
567
637
|
const packageSource = createMigrationPackageSource(args, current);
|
|
568
638
|
updateUltramodernConfig(context.workspaceRoot, packageSource);
|
|
569
639
|
updateReferenceTopology(context.workspaceRoot);
|
|
570
|
-
|
|
640
|
+
const migrated = readUltramodernConfig(context.workspaceRoot);
|
|
641
|
+
updateGeneratedTypeScriptSurfaces(context.workspaceRoot, migrated);
|
|
642
|
+
updateGeneratedModernConfigs(context.workspaceRoot, migrated);
|
|
571
643
|
for (const relativePackageFile of listWorkspacePackageFiles(context.workspaceRoot)){
|
|
572
644
|
const packageFile = node_path.join(context.workspaceRoot, relativePackageFile);
|
|
573
645
|
const packageJson = readJsonFile(packageFile);
|
|
@@ -586,7 +658,9 @@ and pnpm contract:check.
|
|
|
586
658
|
else if ('package.json' === relativePackageFile) writeJsonFile(packageFile, packageJson);
|
|
587
659
|
}
|
|
588
660
|
updateGeneratedPnpmWorkspacePolicy(context.workspaceRoot);
|
|
589
|
-
ensureGeneratedDeclarationPatches(context.workspaceRoot
|
|
661
|
+
ensureGeneratedDeclarationPatches(context.workspaceRoot, {
|
|
662
|
+
includeDrizzleOrmPatch: workspaceUsesDependency(context.workspaceRoot, 'drizzle-orm')
|
|
663
|
+
});
|
|
590
664
|
if (!hasFlag(args, '--skip-install')) {
|
|
591
665
|
const status = runPnpmLockfileRefresh(context);
|
|
592
666
|
if (0 !== status) return status;
|
|
@@ -93,8 +93,10 @@ ${defaultAssetPrefixSource}
|
|
|
93
93
|
// load remoteEntry.js and exposed chunks from the remote origin, not the host.
|
|
94
94
|
const assetPrefix =
|
|
95
95
|
configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix;
|
|
96
|
-
const
|
|
97
|
-
const
|
|
96
|
+
const buildTarget = cloudflareDeployEnabled ? 'cloudflare' : 'web';
|
|
97
|
+
const buildOutputRoot = cloudflareDeployEnabled ? 'dist-cloudflare' : 'dist';
|
|
98
|
+
const buildTempDirectory = \`node_modules/.modern-js-\${appId}-\${buildTarget}\`;
|
|
99
|
+
const buildCacheDirectory = \`node_modules/.cache/rspack-\${appId}-\${buildTarget}\`;
|
|
98
100
|
|
|
99
101
|
if (
|
|
100
102
|
cloudflareDeployEnabled &&
|
|
@@ -136,13 +138,15 @@ ${bffConfig} ...(cloudflareDeployEnabled
|
|
|
136
138
|
disableTsChecker: false,
|
|
137
139
|
distPath: {
|
|
138
140
|
html: './',
|
|
141
|
+
root: buildOutputRoot,
|
|
139
142
|
},
|
|
140
143
|
polyfill: 'off',
|
|
141
144
|
splitRouteChunks: true,
|
|
145
|
+
tempDir: buildTempDirectory,
|
|
142
146
|
},
|
|
143
147
|
performance: {
|
|
144
148
|
buildCache: {
|
|
145
|
-
cacheDigest: [appId,
|
|
149
|
+
cacheDigest: [appId, buildTarget],
|
|
146
150
|
cacheDirectory: buildCacheDirectory,
|
|
147
151
|
},
|
|
148
152
|
rsdoctor: {
|
|
@@ -356,7 +356,6 @@ function createRootTsConfig(apps = []) {
|
|
|
356
356
|
}
|
|
357
357
|
function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [], bridge) {
|
|
358
358
|
const publicSurfaceBuildCommand = createPublicSurfaceGenerationCommand(app, 'dist');
|
|
359
|
-
const publicSurfaceCloudflareBuildCommand = createPublicSurfaceGenerationCommand(app, 'dist');
|
|
360
359
|
const publicSurfaceCloudflareOutputCommand = createPublicSurfaceGenerationCommand(app, 'cloudflare');
|
|
361
360
|
const packageExports = Object.fromEntries(Object.entries(app.exposes ?? {}).map(([expose, source])=>[
|
|
362
361
|
expose,
|
|
@@ -369,7 +368,7 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
|
|
|
369
368
|
scripts: {
|
|
370
369
|
dev: 'modern dev',
|
|
371
370
|
build: app.exposes ? `ULTRAMODERN_ZEPHYR=false modern build && ${publicSurfaceBuildCommand} && node ${relativeRootFor(app.directory)}/scripts/assert-mf-types.mts` : `ULTRAMODERN_ZEPHYR=false modern build && ${publicSurfaceBuildCommand}`,
|
|
372
|
-
'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build &&
|
|
371
|
+
'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build && ${publicSurfaceCloudflareOutputCommand}`,
|
|
373
372
|
'cloudflare:deploy': 'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS=true pnpm run cloudflare:build && wrangler deploy --config .output/wrangler.json',
|
|
374
373
|
'cloudflare:preview': 'pnpm run cloudflare:build && wrangler dev --config .output/wrangler.json',
|
|
375
374
|
'cloudflare:proof': `node ${relativeRootFor(app.directory)}/scripts/proof-cloudflare-version.mts --app ${app.id}`,
|
|
@@ -8,6 +8,7 @@ import { resolveCreatePackageRoot } from "../create-package-root.js";
|
|
|
8
8
|
import { BLEEDINGDEV_PACKAGE_NAME_PREFIX, BLEEDINGDEV_PACKAGE_SCOPE, ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES, ULTRAMODERN_WORKSPACE_MODERN_PACKAGES, WORKSPACE_PACKAGE_VERSION, modernPackageSpecifier } from "../ultramodern-package-source.js";
|
|
9
9
|
import { createAppEnvDts } from "../ultramodern-workspace/app-files.js";
|
|
10
10
|
import { validateModuleFederationTypes } from "../ultramodern-workspace/mf-validation.js";
|
|
11
|
+
import { createAppModernConfig } from "../ultramodern-workspace/module-federation.js";
|
|
11
12
|
import { createAppMfTypesTsConfig, createAppTsConfig, createSharedPackageTsConfig, createTsConfigBase } from "../ultramodern-workspace/package-json.js";
|
|
12
13
|
import { DRIZZLE_ORM_VERSION, EFFECT_TSGO_VERSION, EFFECT_VERSION, EFFECT_VITEST_VERSION, OXFMT_VERSION, OXLINT_VERSION, TYPESCRIPT_NATIVE_PREVIEW_VERSION, WRANGLER_VERSION, ZEPHYR_AGENT_VERSION, ZEPHYR_RSPACK_PLUGIN_VERSION } from "../ultramodern-workspace/versions.js";
|
|
13
14
|
import { createWorkspaceValidationScript } from "../ultramodern-workspace/workspace-scripts.js";
|
|
@@ -220,9 +221,14 @@ function updateGeneratedPackageScripts(packageJson) {
|
|
|
220
221
|
if (!scripts || 'object' != typeof scripts || Array.isArray(scripts)) return false;
|
|
221
222
|
let changed = false;
|
|
222
223
|
const cloudflareBuild = scripts['cloudflare:build'];
|
|
223
|
-
if ('string' == typeof cloudflareBuild
|
|
224
|
-
|
|
225
|
-
|
|
224
|
+
if ('string' == typeof cloudflareBuild) {
|
|
225
|
+
let nextCloudflareBuild = cloudflareBuild;
|
|
226
|
+
if (nextCloudflareBuild.includes(cloudflareModernDeployCommand) && !nextCloudflareBuild.includes(cloudflareModernDeploySkipBuildCommand)) nextCloudflareBuild = nextCloudflareBuild.replace(cloudflareModernDeployCommand, cloudflareModernDeploySkipBuildCommand);
|
|
227
|
+
nextCloudflareBuild = nextCloudflareBuild.replace(/ && node \S*scripts\/generate-public-surface-assets\.m[ct]s --app [^&]+ --target dist(?= && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build)/u, '');
|
|
228
|
+
if (nextCloudflareBuild !== cloudflareBuild) {
|
|
229
|
+
scripts['cloudflare:build'] = nextCloudflareBuild;
|
|
230
|
+
changed = true;
|
|
231
|
+
}
|
|
226
232
|
}
|
|
227
233
|
const cloudflareDeploy = scripts['cloudflare:deploy'];
|
|
228
234
|
if ('string' == typeof cloudflareDeploy && cloudflareDeploy.includes(cloudflareWranglerDeployInvalidSkipBuildCommand)) {
|
|
@@ -361,6 +367,19 @@ function ensureYamlMapEntry(source, key, entryKey, value) {
|
|
|
361
367
|
changed: true
|
|
362
368
|
};
|
|
363
369
|
}
|
|
370
|
+
function removeYamlMapEntry(source, entryKey) {
|
|
371
|
+
const packageName = entryKey.includes('@') ? entryKey.slice(0, entryKey.lastIndexOf('@')) : entryKey;
|
|
372
|
+
const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
373
|
+
const currentEntryPattern = new RegExp(`^ {2}'${escapedPackageName}@[^']+': .+\\n?`, 'mu');
|
|
374
|
+
if (!currentEntryPattern.test(source)) return {
|
|
375
|
+
source,
|
|
376
|
+
changed: false
|
|
377
|
+
};
|
|
378
|
+
return {
|
|
379
|
+
source: source.replace(currentEntryPattern, ''),
|
|
380
|
+
changed: true
|
|
381
|
+
};
|
|
382
|
+
}
|
|
364
383
|
function ensureGeneratedPatchFile(workspaceRoot, relativePatchPath, sourcePatchPath) {
|
|
365
384
|
const targetPath = node_path.join(workspaceRoot, relativePatchPath);
|
|
366
385
|
const patch = node_fs.readFileSync(sourcePatchPath, 'utf-8');
|
|
@@ -371,10 +390,53 @@ function ensureGeneratedPatchFile(workspaceRoot, relativePatchPath, sourcePatchP
|
|
|
371
390
|
node_fs.writeFileSync(targetPath, patch, 'utf-8');
|
|
372
391
|
return true;
|
|
373
392
|
}
|
|
374
|
-
function
|
|
393
|
+
function removeGeneratedPatchFileIfUnchanged(workspaceRoot, relativePatchPath, sourcePatchPath) {
|
|
394
|
+
const targetPath = node_path.join(workspaceRoot, relativePatchPath);
|
|
395
|
+
if (!node_fs.existsSync(targetPath)) return false;
|
|
396
|
+
const patch = node_fs.readFileSync(sourcePatchPath, 'utf-8');
|
|
397
|
+
if (node_fs.readFileSync(targetPath, 'utf-8') !== patch) return false;
|
|
398
|
+
node_fs.rmSync(targetPath);
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
function workspaceUsesDependency(workspaceRoot, packageName) {
|
|
402
|
+
const packageJsonPaths = [
|
|
403
|
+
node_path.join(workspaceRoot, 'package.json')
|
|
404
|
+
];
|
|
405
|
+
for (const workspaceDir of [
|
|
406
|
+
'apps',
|
|
407
|
+
'verticals',
|
|
408
|
+
'packages'
|
|
409
|
+
]){
|
|
410
|
+
const absoluteWorkspaceDir = node_path.join(workspaceRoot, workspaceDir);
|
|
411
|
+
if (node_fs.existsSync(absoluteWorkspaceDir)) for (const entry of node_fs.readdirSync(absoluteWorkspaceDir, {
|
|
412
|
+
withFileTypes: true
|
|
413
|
+
})){
|
|
414
|
+
if (!entry.isDirectory()) continue;
|
|
415
|
+
const packageJsonPath = node_path.join(absoluteWorkspaceDir, entry.name, 'package.json');
|
|
416
|
+
if (node_fs.existsSync(packageJsonPath)) packageJsonPaths.push(packageJsonPath);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
for (const packageJsonPath of packageJsonPaths){
|
|
420
|
+
const packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
421
|
+
for (const field of [
|
|
422
|
+
'dependencies',
|
|
423
|
+
'devDependencies',
|
|
424
|
+
'peerDependencies',
|
|
425
|
+
'optionalDependencies'
|
|
426
|
+
]){
|
|
427
|
+
const dependencies = packageJson[field];
|
|
428
|
+
if (dependencies && 'object' == typeof dependencies) {
|
|
429
|
+
if (Object.prototype.hasOwnProperty.call(dependencies, packageName)) return true;
|
|
430
|
+
for (const specifier of Object.values(dependencies))if ('string' == typeof specifier && specifier.startsWith(`npm:${packageName}@`)) return true;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
function ensureGeneratedDeclarationPatches(workspaceRoot, options) {
|
|
375
437
|
let changed = false;
|
|
376
438
|
changed = ensureGeneratedPatchFile(workspaceRoot, effectDeclarationPatchPath, effectDeclarationPatchSourcePath) || changed;
|
|
377
|
-
changed = ensureGeneratedPatchFile(workspaceRoot, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed;
|
|
439
|
+
changed = options.includeDrizzleOrmPatch ? ensureGeneratedPatchFile(workspaceRoot, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed : removeGeneratedPatchFileIfUnchanged(workspaceRoot, drizzleOrmDeclarationPatchPath, drizzleOrmDeclarationPatchSourcePath) || changed;
|
|
378
440
|
return changed;
|
|
379
441
|
}
|
|
380
442
|
function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
@@ -382,6 +444,7 @@ function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
|
382
444
|
if (!node_fs.existsSync(workspaceFile)) return false;
|
|
383
445
|
let source = node_fs.readFileSync(workspaceFile, 'utf-8');
|
|
384
446
|
let changed = false;
|
|
447
|
+
const usesDrizzleOrm = workspaceUsesDependency(workspaceRoot, 'drizzle-orm');
|
|
385
448
|
const replacements = [
|
|
386
449
|
[
|
|
387
450
|
/^ {4}'@effect\/vitest>effect': .+$/mu,
|
|
@@ -419,7 +482,7 @@ function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
|
|
|
419
482
|
const effectPatch = ensureYamlMapEntry(source, 'patchedDependencies', `effect@${EFFECT_VERSION}`, effectDeclarationPatchPath);
|
|
420
483
|
source = effectPatch.source;
|
|
421
484
|
changed = effectPatch.changed || changed;
|
|
422
|
-
const drizzleOrmPatch = ensureYamlMapEntry(source, 'patchedDependencies', `drizzle-orm@${DRIZZLE_ORM_VERSION}`, drizzleOrmDeclarationPatchPath);
|
|
485
|
+
const drizzleOrmPatch = usesDrizzleOrm ? ensureYamlMapEntry(source, 'patchedDependencies', `drizzle-orm@${DRIZZLE_ORM_VERSION}`, drizzleOrmDeclarationPatchPath) : removeYamlMapEntry(source, `drizzle-orm@${DRIZZLE_ORM_VERSION}`);
|
|
423
486
|
source = drizzleOrmPatch.source;
|
|
424
487
|
changed = drizzleOrmPatch.changed || changed;
|
|
425
488
|
if (changed) node_fs.writeFileSync(workspaceFile, source, 'utf-8');
|
|
@@ -468,7 +531,8 @@ function ensureGeneratedIgnoreRules(workspaceRoot) {
|
|
|
468
531
|
let changed = false;
|
|
469
532
|
for (const rule of [
|
|
470
533
|
'.mf/',
|
|
471
|
-
'**/.mf/'
|
|
534
|
+
'**/.mf/',
|
|
535
|
+
'dist-cloudflare/'
|
|
472
536
|
])if (!lines.includes(rule)) {
|
|
473
537
|
lines.push(rule);
|
|
474
538
|
changed = true;
|
|
@@ -495,6 +559,12 @@ function updateGeneratedTypeScriptSurfaces(workspaceRoot, config) {
|
|
|
495
559
|
}
|
|
496
560
|
return changed;
|
|
497
561
|
}
|
|
562
|
+
function updateGeneratedModernConfigs(workspaceRoot, config) {
|
|
563
|
+
let changed = false;
|
|
564
|
+
const apps = workspaceAppsFromToolingConfig(config);
|
|
565
|
+
for (const app of apps)changed = writeTextIfChanged(node_path.join(workspaceRoot, app.directory, 'modern.config.ts'), createAppModernConfig(config.workspace.packageScope, app)) || changed;
|
|
566
|
+
return changed;
|
|
567
|
+
}
|
|
498
568
|
function updateReferenceTopology(workspaceRoot) {
|
|
499
569
|
const topologyPath = node_path.join(workspaceRoot, 'topology/reference-topology.json');
|
|
500
570
|
if (!node_fs.existsSync(topologyPath)) return false;
|
|
@@ -568,7 +638,9 @@ and pnpm contract:check.
|
|
|
568
638
|
const packageSource = createMigrationPackageSource(args, current);
|
|
569
639
|
updateUltramodernConfig(context.workspaceRoot, packageSource);
|
|
570
640
|
updateReferenceTopology(context.workspaceRoot);
|
|
571
|
-
|
|
641
|
+
const migrated = readUltramodernConfig(context.workspaceRoot);
|
|
642
|
+
updateGeneratedTypeScriptSurfaces(context.workspaceRoot, migrated);
|
|
643
|
+
updateGeneratedModernConfigs(context.workspaceRoot, migrated);
|
|
572
644
|
for (const relativePackageFile of listWorkspacePackageFiles(context.workspaceRoot)){
|
|
573
645
|
const packageFile = node_path.join(context.workspaceRoot, relativePackageFile);
|
|
574
646
|
const packageJson = readJsonFile(packageFile);
|
|
@@ -587,7 +659,9 @@ and pnpm contract:check.
|
|
|
587
659
|
else if ('package.json' === relativePackageFile) writeJsonFile(packageFile, packageJson);
|
|
588
660
|
}
|
|
589
661
|
updateGeneratedPnpmWorkspacePolicy(context.workspaceRoot);
|
|
590
|
-
ensureGeneratedDeclarationPatches(context.workspaceRoot
|
|
662
|
+
ensureGeneratedDeclarationPatches(context.workspaceRoot, {
|
|
663
|
+
includeDrizzleOrmPatch: workspaceUsesDependency(context.workspaceRoot, 'drizzle-orm')
|
|
664
|
+
});
|
|
591
665
|
if (!hasFlag(args, '--skip-install')) {
|
|
592
666
|
const status = runPnpmLockfileRefresh(context);
|
|
593
667
|
if (0 !== status) return status;
|
|
@@ -94,8 +94,10 @@ ${defaultAssetPrefixSource}
|
|
|
94
94
|
// load remoteEntry.js and exposed chunks from the remote origin, not the host.
|
|
95
95
|
const assetPrefix =
|
|
96
96
|
configuredModernAssetPrefix || configuredUltramodernAssetPrefix || defaultAssetPrefix;
|
|
97
|
-
const
|
|
98
|
-
const
|
|
97
|
+
const buildTarget = cloudflareDeployEnabled ? 'cloudflare' : 'web';
|
|
98
|
+
const buildOutputRoot = cloudflareDeployEnabled ? 'dist-cloudflare' : 'dist';
|
|
99
|
+
const buildTempDirectory = \`node_modules/.modern-js-\${appId}-\${buildTarget}\`;
|
|
100
|
+
const buildCacheDirectory = \`node_modules/.cache/rspack-\${appId}-\${buildTarget}\`;
|
|
99
101
|
|
|
100
102
|
if (
|
|
101
103
|
cloudflareDeployEnabled &&
|
|
@@ -137,13 +139,15 @@ ${bffConfig} ...(cloudflareDeployEnabled
|
|
|
137
139
|
disableTsChecker: false,
|
|
138
140
|
distPath: {
|
|
139
141
|
html: './',
|
|
142
|
+
root: buildOutputRoot,
|
|
140
143
|
},
|
|
141
144
|
polyfill: 'off',
|
|
142
145
|
splitRouteChunks: true,
|
|
146
|
+
tempDir: buildTempDirectory,
|
|
143
147
|
},
|
|
144
148
|
performance: {
|
|
145
149
|
buildCache: {
|
|
146
|
-
cacheDigest: [appId,
|
|
150
|
+
cacheDigest: [appId, buildTarget],
|
|
147
151
|
cacheDirectory: buildCacheDirectory,
|
|
148
152
|
},
|
|
149
153
|
rsdoctor: {
|
|
@@ -357,7 +357,6 @@ function createRootTsConfig(apps = []) {
|
|
|
357
357
|
}
|
|
358
358
|
function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [], bridge) {
|
|
359
359
|
const publicSurfaceBuildCommand = createPublicSurfaceGenerationCommand(app, 'dist');
|
|
360
|
-
const publicSurfaceCloudflareBuildCommand = createPublicSurfaceGenerationCommand(app, 'dist');
|
|
361
360
|
const publicSurfaceCloudflareOutputCommand = createPublicSurfaceGenerationCommand(app, 'cloudflare');
|
|
362
361
|
const packageExports = Object.fromEntries(Object.entries(app.exposes ?? {}).map(([expose, source])=>[
|
|
363
362
|
expose,
|
|
@@ -370,7 +369,7 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
|
|
|
370
369
|
scripts: {
|
|
371
370
|
dev: 'modern dev',
|
|
372
371
|
build: app.exposes ? `ULTRAMODERN_ZEPHYR=false modern build && ${publicSurfaceBuildCommand} && node ${relativeRootFor(app.directory)}/scripts/assert-mf-types.mts` : `ULTRAMODERN_ZEPHYR=false modern build && ${publicSurfaceBuildCommand}`,
|
|
373
|
-
'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build &&
|
|
372
|
+
'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build && ${publicSurfaceCloudflareOutputCommand}`,
|
|
374
373
|
'cloudflare:deploy': 'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS=true pnpm run cloudflare:build && wrangler deploy --config .output/wrangler.json',
|
|
375
374
|
'cloudflare:preview': 'pnpm run cloudflare:build && wrangler dev --config .output/wrangler.json',
|
|
376
375
|
'cloudflare:proof': `node ${relativeRootFor(app.directory)}/scripts/proof-cloudflare-version.mts --app ${app.id}`,
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20"
|
|
23
23
|
},
|
|
24
|
-
"version": "3.5.0-ultramodern.
|
|
24
|
+
"version": "3.5.0-ultramodern.13",
|
|
25
25
|
"types": "./dist/types/index.d.ts",
|
|
26
26
|
"main": "./dist/esm-node/index.js",
|
|
27
27
|
"bin": {
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"@modern-js/codesmith": "2.6.9",
|
|
78
78
|
"oxfmt": "0.56.0",
|
|
79
79
|
"ultracite": "7.8.3",
|
|
80
|
-
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.5.0-ultramodern.
|
|
80
|
+
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.5.0-ultramodern.13"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@rslib/core": "0.23.1",
|
|
@@ -99,6 +99,6 @@
|
|
|
99
99
|
"test": "rm -rf dist && rslib build -c rslibconfig.mts && rstest --passWithNoTests"
|
|
100
100
|
},
|
|
101
101
|
"ultramodern": {
|
|
102
|
-
"frameworkVersion": "3.5.0-ultramodern.
|
|
102
|
+
"frameworkVersion": "3.5.0-ultramodern.13"
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -63,5 +63,4 @@ allowBuilds:
|
|
|
63
63
|
|
|
64
64
|
patchedDependencies:
|
|
65
65
|
'@tanstack/router-core@{{tanstackRouterCoreVersion}}': patches/@tanstack__router-core@{{tanstackRouterCoreVersion}}.patch
|
|
66
|
-
'drizzle-orm@{{drizzleOrmVersion}}': patches/drizzle-orm-ts7-strict-declarations.patch
|
|
67
66
|
'effect@{{effectVersion}}': patches/effect-schema-error-type-id.patch
|
|
@@ -1363,12 +1363,17 @@ const extractAssetPrefixExpression = modernConfig => {
|
|
|
1363
1363
|
assert(match?.groups?.expression, 'modern.config.ts must assign assetPrefix');
|
|
1364
1364
|
return match.groups.expression;
|
|
1365
1365
|
};
|
|
1366
|
-
const
|
|
1366
|
+
const assertTargetIsolatedBuildArtifacts = (appId, modernConfig) => {
|
|
1367
1367
|
assert(
|
|
1368
|
-
modernConfig.includes("const
|
|
1369
|
-
modernConfig.includes(
|
|
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],') &&
|
|
1370
1375
|
modernConfig.includes('cacheDirectory: buildCacheDirectory,'),
|
|
1371
|
-
`${appId} must
|
|
1376
|
+
`${appId} must isolate build output, Modern temp files, and Rspack cache by app and build target`,
|
|
1372
1377
|
);
|
|
1373
1378
|
};
|
|
1374
1379
|
const assertCloudflareBuildSkipsDeployRebuild = (appId, packageJson) => {
|
|
@@ -1378,6 +1383,12 @@ const assertCloudflareBuildSkipsDeployRebuild = (appId, packageJson) => {
|
|
|
1378
1383
|
),
|
|
1379
1384
|
`${appId} cloudflare:build must deploy with --skip-build after the explicit Cloudflare build`,
|
|
1380
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
|
+
);
|
|
1381
1392
|
};
|
|
1382
1393
|
const stripYamlInlineComment = value => {
|
|
1383
1394
|
let quote = undefined;
|
|
@@ -1795,6 +1806,7 @@ const shellRouteHead = readText('apps/shell-super-app/src/routes/ultramodern-rou
|
|
|
1795
1806
|
const shellRouteMetadata = readText('apps/shell-super-app/src/routes/ultramodern-route-metadata.ts');
|
|
1796
1807
|
assert(/^\.mf\/$/mu.test(gitignore), 'Generated .gitignore must ignore root Module Federation diagnostics');
|
|
1797
1808
|
assert(/^\*\*\/\.mf\/$/mu.test(gitignore), 'Generated .gitignore must ignore per-app Module Federation diagnostics');
|
|
1809
|
+
assert(/^dist-cloudflare\/$/mu.test(gitignore), 'Generated .gitignore must ignore Cloudflare build output');
|
|
1798
1810
|
assert(shellModernAppEnv.includes("import '@modern-js/app-tools/types';"), 'Shell app env must import the framework-owned app ambient type bundle through module resolution');
|
|
1799
1811
|
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');
|
|
1800
1812
|
assert(!shellModernAppEnv.includes("declare module '*.svg'"), 'Shell app env must not redeclare framework-owned svg asset modules');
|
|
@@ -1818,7 +1830,7 @@ assert(shellPackage.dependencies?.['@modern-js/plugin-i18n'] === expectedModernP
|
|
|
1818
1830
|
assert(shellPackage.dependencies?.['@modern-js/plugin-tanstack'] === expectedModernPackageSpecifier('@modern-js/plugin-tanstack'), 'Shell plugin-tanstack dependency must match package source metadata');
|
|
1819
1831
|
assert(shellPackage.dependencies?.['@modern-js/runtime'] === expectedModernPackageSpecifier('@modern-js/runtime'), 'Shell runtime dependency must match package source metadata');
|
|
1820
1832
|
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');
|
|
1821
|
-
|
|
1833
|
+
assertTargetIsolatedBuildArtifacts('shell-super-app', shellModernConfig);
|
|
1822
1834
|
assertCloudflareBuildSkipsDeployRebuild('shell-super-app', shellPackage);
|
|
1823
1835
|
const shellContract = generatedContract.apps?.find(app => app.id === 'shell-super-app');
|
|
1824
1836
|
assert(shellContract?.deploy?.cloudflare?.workerName === expectedWorkerName('shell-super-app'), 'Shell Cloudflare workerName is incorrect');
|
|
@@ -1901,7 +1913,7 @@ for (const vertical of fullStackVerticals) {
|
|
|
1901
1913
|
assert(routeMetadata.includes("authoring: 'colocated-route-meta'"), `${vertical.id} route metadata manifest must advertise colocated authoring`);
|
|
1902
1914
|
assert(packageJson.name === vertical.packageName, `${vertical.id} package name is incorrect`);
|
|
1903
1915
|
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`);
|
|
1904
|
-
|
|
1916
|
+
assertTargetIsolatedBuildArtifacts(vertical.id, modernConfig);
|
|
1905
1917
|
assertCloudflareBuildSkipsDeployRebuild(vertical.id, packageJson);
|
|
1906
1918
|
assert(packageJson.scripts?.['cloudflare:proof']?.includes(`--app ${vertical.id}`), `${vertical.id} must expose cloudflare:proof`);
|
|
1907
1919
|
assert(packageJson.devDependencies?.['@modern-js/app-tools'] === expectedModernPackageSpecifier('@modern-js/app-tools'), `${vertical.id} app-tools dependency must match package source metadata`);
|