@bleedingdev/modern-js-create 3.5.0-ultramodern.0 → 3.5.0-ultramodern.10

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.
Files changed (28) hide show
  1. package/README.md +28 -0
  2. package/dist/cjs/ultramodern-tooling/commands.cjs +399 -0
  3. package/dist/cjs/ultramodern-workspace/contracts.cjs +1 -0
  4. package/dist/cjs/ultramodern-workspace/module-federation.cjs +6 -0
  5. package/dist/cjs/ultramodern-workspace/package-json.cjs +2 -1
  6. package/dist/cjs/ultramodern-workspace/versions.cjs +12 -2
  7. package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +1 -0
  8. package/dist/cjs/ultramodern-workspace/write-workspace.cjs +2 -0
  9. package/dist/esm/ultramodern-tooling/commands.js +399 -0
  10. package/dist/esm/ultramodern-workspace/contracts.js +1 -0
  11. package/dist/esm/ultramodern-workspace/module-federation.js +6 -0
  12. package/dist/esm/ultramodern-workspace/package-json.js +2 -1
  13. package/dist/esm/ultramodern-workspace/versions.js +7 -3
  14. package/dist/esm/ultramodern-workspace/workspace-scripts.js +1 -0
  15. package/dist/esm/ultramodern-workspace/write-workspace.js +3 -1
  16. package/dist/esm-node/ultramodern-tooling/commands.js +399 -0
  17. package/dist/esm-node/ultramodern-workspace/contracts.js +1 -0
  18. package/dist/esm-node/ultramodern-workspace/module-federation.js +6 -0
  19. package/dist/esm-node/ultramodern-workspace/package-json.js +2 -1
  20. package/dist/esm-node/ultramodern-workspace/versions.js +7 -3
  21. package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +1 -0
  22. package/dist/esm-node/ultramodern-workspace/write-workspace.js +3 -1
  23. package/dist/types/ultramodern-workspace/versions.d.ts +6 -2
  24. package/package.json +6 -6
  25. package/template-workspace/README.md.handlebars +44 -1
  26. package/template-workspace/pnpm-workspace.yaml.handlebars +8 -0
  27. package/templates/workspace-scripts/check-ultramodern-api-boundaries.mts +30 -8
  28. package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +23 -0
package/README.md CHANGED
@@ -189,6 +189,34 @@ mise exec -- pnpm check
189
189
  mise exec -- pnpm build
190
190
  ```
191
191
 
192
+ For strict Effect API migrations, update generated package metadata and Modern
193
+ package aliases through the framework command before hand-editing app code:
194
+
195
+ ```bash
196
+ pnpm dlx @bleedingdev/modern-js-create@3.5.0-ultramodern.10 ultramodern \
197
+ migrate-strict-effect --version 3.5.0-ultramodern.10
198
+ pnpm api:check
199
+ pnpm contract:check
200
+ pnpm check
201
+ pnpm build
202
+ ```
203
+
204
+ The command updates `.modernjs/ultramodern.json`, root `modernjs.packageSource`,
205
+ generated Modern package aliases, framework-owned toolchain pins, old direct
206
+ topology metadata, strict Effect pnpm overrides/trust policy, and the pnpm
207
+ lockfile. It does not invent compatibility shims or move business code behind
208
+ your back. If `pnpm api:check` still fails, migrate the source to
209
+ `shared/api.ts`, `api/index.ts`, and `src/api/*-client.ts` and delete
210
+ `api/effect`, `api/lambda`, `shared/effect`, and `src/effect` paths.
211
+
212
+ Generated strict Effect workspaces pin the compatible Effect cohort through
213
+ `pnpm-workspace.yaml` overrides: `effect@4.0.0-beta.91` and
214
+ `@effect/vitest@4.0.0-beta.91`. The generated pnpm policy also excludes the
215
+ known `effect@4.0.0-beta.91` and `@effect/opentelemetry@4.0.0-beta.91`
216
+ versions from the 24-hour minimum-release-age gate and their trusted-publisher
217
+ to provenance transitions from no-downgrade checks. Do not override those in
218
+ app packages; update the framework cohort when the runtime moves.
219
+
192
220
  Use `--ultramodern-package-source=install` for published cohort proof and pin a
193
221
  specific release with `--ultramodern-package-version` when CI must prove an
194
222
  exact framework version. Keep `--workspace` only for local monorepo testing
@@ -51,7 +51,9 @@ const external_node_path_namespaceObject = require("node:path");
51
51
  var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
52
52
  const external_node_url_namespaceObject = require("node:url");
53
53
  const external_create_package_root_cjs_namespaceObject = require("../create-package-root.cjs");
54
+ const external_ultramodern_package_source_cjs_namespaceObject = require("../ultramodern-package-source.cjs");
54
55
  const mf_validation_cjs_namespaceObject = require("../ultramodern-workspace/mf-validation.cjs");
56
+ const versions_cjs_namespaceObject = require("../ultramodern-workspace/versions.cjs");
55
57
  const workspace_scripts_cjs_namespaceObject = require("../ultramodern-workspace/workspace-scripts.cjs");
56
58
  const external_config_cjs_namespaceObject = require("./config.cjs");
57
59
  const commands_dirname = external_node_path_default().dirname((0, external_node_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__));
@@ -64,6 +66,7 @@ Commands:
64
66
  validate
65
67
  typecheck
66
68
  mf-types
69
+ migrate-strict-effect
67
70
  public-surface
68
71
  cloudflare-proof
69
72
  performance-readiness
@@ -129,6 +132,400 @@ Checks real Module Federation config files and DTS archives for exposed apps.
129
132
  });
130
133
  return 0;
131
134
  }
135
+ const modernPackageNames = new Set([
136
+ ...external_ultramodern_package_source_cjs_namespaceObject.ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES,
137
+ ...external_ultramodern_package_source_cjs_namespaceObject.ULTRAMODERN_WORKSPACE_MODERN_PACKAGES
138
+ ]);
139
+ function readJsonFile(filePath) {
140
+ return JSON.parse(external_node_fs_default().readFileSync(filePath, 'utf-8'));
141
+ }
142
+ function writeJsonFile(filePath, value) {
143
+ external_node_fs_default().writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf-8');
144
+ }
145
+ function readOption(args, name) {
146
+ const prefix = `${name}=`;
147
+ const inline = args.find((arg)=>arg.startsWith(prefix));
148
+ if (inline) {
149
+ const value = inline.slice(prefix.length);
150
+ if (!value) throw new Error(`${name} needs a value.`);
151
+ return value;
152
+ }
153
+ const index = args.indexOf(name);
154
+ if (-1 === index) return;
155
+ const value = args[index + 1];
156
+ if (!value || value.startsWith('--')) throw new Error(`${name} needs a value.`);
157
+ return value;
158
+ }
159
+ function hasFlag(args, name) {
160
+ return args.includes(name);
161
+ }
162
+ function listWorkspacePackageFiles(workspaceRoot) {
163
+ const packageFiles = [
164
+ 'package.json'
165
+ ];
166
+ for (const directory of [
167
+ 'apps',
168
+ 'verticals',
169
+ 'packages'
170
+ ]){
171
+ const absoluteDirectory = external_node_path_default().join(workspaceRoot, directory);
172
+ if (external_node_fs_default().existsSync(absoluteDirectory)) for (const entry of external_node_fs_default().readdirSync(absoluteDirectory, {
173
+ withFileTypes: true
174
+ })){
175
+ if (!entry.isDirectory()) continue;
176
+ const packageFile = external_node_path_default().join(directory, entry.name, 'package.json');
177
+ if (external_node_fs_default().existsSync(external_node_path_default().join(workspaceRoot, packageFile))) packageFiles.push(packageFile);
178
+ }
179
+ }
180
+ return packageFiles;
181
+ }
182
+ function updateModernDependencies(packageJson, packageSource) {
183
+ let changed = false;
184
+ for (const section of [
185
+ 'dependencies',
186
+ 'devDependencies',
187
+ 'peerDependencies',
188
+ 'optionalDependencies'
189
+ ]){
190
+ const dependencies = packageJson[section];
191
+ if (!(!dependencies || 'object' != typeof dependencies || Array.isArray(dependencies))) for (const packageName of Object.keys(dependencies)){
192
+ if (!modernPackageNames.has(packageName)) continue;
193
+ const nextSpecifier = (0, external_ultramodern_package_source_cjs_namespaceObject.modernPackageSpecifier)(packageName, packageSource);
194
+ if (dependencies[packageName] !== nextSpecifier) {
195
+ dependencies[packageName] = nextSpecifier;
196
+ changed = true;
197
+ }
198
+ }
199
+ }
200
+ return changed;
201
+ }
202
+ const generatedToolingDependencyPins = new Map([
203
+ [
204
+ '@effect/tsgo',
205
+ versions_cjs_namespaceObject.EFFECT_TSGO_VERSION
206
+ ],
207
+ [
208
+ "@typescript/native-preview",
209
+ versions_cjs_namespaceObject.TYPESCRIPT_NATIVE_PREVIEW_VERSION
210
+ ],
211
+ [
212
+ 'oxfmt',
213
+ versions_cjs_namespaceObject.OXFMT_VERSION
214
+ ],
215
+ [
216
+ 'oxlint',
217
+ versions_cjs_namespaceObject.OXLINT_VERSION
218
+ ],
219
+ [
220
+ 'wrangler',
221
+ versions_cjs_namespaceObject.WRANGLER_VERSION
222
+ ],
223
+ [
224
+ 'zephyr-agent',
225
+ versions_cjs_namespaceObject.ZEPHYR_AGENT_VERSION
226
+ ],
227
+ [
228
+ 'zephyr-rspack-plugin',
229
+ versions_cjs_namespaceObject.ZEPHYR_RSPACK_PLUGIN_VERSION
230
+ ]
231
+ ]);
232
+ const strictEffectPackageVersionPolicyExclusions = [
233
+ `effect@${versions_cjs_namespaceObject.EFFECT_VERSION}`,
234
+ `@effect/opentelemetry@${versions_cjs_namespaceObject.EFFECT_VERSION}`
235
+ ];
236
+ function updateGeneratedToolingDependencies(packageJson) {
237
+ let changed = false;
238
+ for (const section of [
239
+ 'dependencies',
240
+ 'devDependencies',
241
+ 'peerDependencies',
242
+ 'optionalDependencies'
243
+ ]){
244
+ const dependencies = packageJson[section];
245
+ if (!(!dependencies || 'object' != typeof dependencies || Array.isArray(dependencies))) {
246
+ for (const [packageName, version] of generatedToolingDependencyPins)if (Object.prototype.hasOwnProperty.call(dependencies, packageName) && dependencies[packageName] !== version) {
247
+ dependencies[packageName] = version;
248
+ changed = true;
249
+ }
250
+ }
251
+ }
252
+ return changed;
253
+ }
254
+ const cloudflareModernDeployCommand = 'ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy';
255
+ const cloudflareModernDeploySkipBuildCommand = `${cloudflareModernDeployCommand} --skip-build`;
256
+ const cloudflareWranglerDeployCommand = 'wrangler deploy --config .output/wrangler.json';
257
+ const cloudflareWranglerDeployInvalidSkipBuildCommand = `${cloudflareWranglerDeployCommand} --skip-build`;
258
+ function updateGeneratedPackageScripts(packageJson) {
259
+ const scripts = packageJson.scripts;
260
+ if (!scripts || 'object' != typeof scripts || Array.isArray(scripts)) return false;
261
+ let changed = false;
262
+ const cloudflareBuild = scripts['cloudflare:build'];
263
+ if ('string' == typeof cloudflareBuild && cloudflareBuild.includes(cloudflareModernDeployCommand) && !cloudflareBuild.includes(cloudflareModernDeploySkipBuildCommand)) {
264
+ scripts['cloudflare:build'] = cloudflareBuild.replace(cloudflareModernDeployCommand, cloudflareModernDeploySkipBuildCommand);
265
+ changed = true;
266
+ }
267
+ const cloudflareDeploy = scripts['cloudflare:deploy'];
268
+ if ('string' == typeof cloudflareDeploy && cloudflareDeploy.includes(cloudflareWranglerDeployInvalidSkipBuildCommand)) {
269
+ scripts['cloudflare:deploy'] = cloudflareDeploy.replace(cloudflareWranglerDeployInvalidSkipBuildCommand, cloudflareWranglerDeployCommand);
270
+ changed = true;
271
+ }
272
+ return changed;
273
+ }
274
+ function normalizeStrictEffectApiMetadata(value) {
275
+ const api = value.api;
276
+ if (!api || 'object' != typeof api || Array.isArray(api)) return false;
277
+ let changed = false;
278
+ const oldEffect = api.effect;
279
+ if (oldEffect && 'object' == typeof oldEffect && !Array.isArray(oldEffect)) {
280
+ if (void 0 === api.stem && 'string' == typeof oldEffect.stem) {
281
+ api.stem = oldEffect.stem;
282
+ changed = true;
283
+ }
284
+ if (void 0 === api.prefix && 'string' == typeof oldEffect.prefix) {
285
+ api.prefix = oldEffect.prefix;
286
+ changed = true;
287
+ }
288
+ if (void 0 === api.consumedBy && Array.isArray(oldEffect.consumedBy)) {
289
+ api.consumedBy = oldEffect.consumedBy;
290
+ changed = true;
291
+ }
292
+ delete api.effect;
293
+ changed = true;
294
+ }
295
+ if (void 0 !== api.runtime && 'effect' !== api.runtime) {
296
+ api.runtime = 'effect';
297
+ changed = true;
298
+ }
299
+ if (api.bff && 'object' == typeof api.bff && !Array.isArray(api.bff)) {
300
+ if (true !== api.bff.strictEffectApproach) {
301
+ api.bff.strictEffectApproach = true;
302
+ changed = true;
303
+ }
304
+ }
305
+ if ('string' == typeof value.path) {
306
+ const directServerEntry = `${value.path}/api/index.ts`;
307
+ if ('string' == typeof api.serverEntry && /\/api\/effect\/index\.[cm]?[jt]sx?$/u.test(api.serverEntry)) {
308
+ api.serverEntry = directServerEntry;
309
+ changed = true;
310
+ }
311
+ if (api.contract && 'object' == typeof api.contract && !Array.isArray(api.contract)) {
312
+ if ('./shared/effect/api' === api.contract.export) {
313
+ api.contract.export = './api';
314
+ changed = true;
315
+ }
316
+ if ('string' == typeof api.contract.path && /\/shared\/effect\/api\.[cm]?[jt]sx?$/u.test(api.contract.path)) {
317
+ api.contract.path = `${value.path}/shared/api.ts`;
318
+ changed = true;
319
+ }
320
+ }
321
+ if (api.client && 'object' == typeof api.client && !Array.isArray(api.client)) {
322
+ if ('./effect/client' === api.client.export) {
323
+ api.client.export = './api/client';
324
+ changed = true;
325
+ }
326
+ if ('string' == typeof api.client.path && /\/src\/effect\/[^/]+-client\.[cm]?ts$/u.test(api.client.path)) {
327
+ const basename = external_node_path_default().basename(api.client.path);
328
+ api.client.path = `${value.path}/src/api/${basename}`;
329
+ changed = true;
330
+ }
331
+ }
332
+ if (void 0 === api.serverEntry && 'effect' === api.runtime) {
333
+ api.serverEntry = directServerEntry;
334
+ changed = true;
335
+ }
336
+ }
337
+ return changed;
338
+ }
339
+ function replaceYamlLine(source, pattern, replacement) {
340
+ const updated = source.replace(pattern, replacement);
341
+ return {
342
+ source: updated,
343
+ changed: updated !== source
344
+ };
345
+ }
346
+ function ensureYamlListItem(source, key, item) {
347
+ const itemLine = ` - '${item}'`;
348
+ const headerPattern = new RegExp(`^${key}:\\n(?:(?: - .+\\n)*)`, 'mu');
349
+ const header = source.match(headerPattern);
350
+ if (header) {
351
+ if (header[0].split('\n').includes(itemLine)) return {
352
+ source,
353
+ changed: false
354
+ };
355
+ return {
356
+ source: source.replace(headerPattern, `${header[0]}${itemLine}\n`),
357
+ changed: true
358
+ };
359
+ }
360
+ const block = `${key}:\n${itemLine}\n`;
361
+ const afterTrustPolicyIgnore = source.replace(/^(trustPolicyIgnoreAfter: .+\n)/mu, `$1${block}`);
362
+ if (afterTrustPolicyIgnore !== source) return {
363
+ source: afterTrustPolicyIgnore,
364
+ changed: true
365
+ };
366
+ return {
367
+ source: `${source.trimEnd()}\n${block}`,
368
+ changed: true
369
+ };
370
+ }
371
+ function updateGeneratedPnpmWorkspacePolicy(workspaceRoot) {
372
+ const workspaceFile = external_node_path_default().join(workspaceRoot, 'pnpm-workspace.yaml');
373
+ if (!external_node_fs_default().existsSync(workspaceFile)) return false;
374
+ let source = external_node_fs_default().readFileSync(workspaceFile, 'utf-8');
375
+ let changed = false;
376
+ const replacements = [
377
+ [
378
+ /^ {4}'@effect\/vitest>effect': .+$/mu,
379
+ ` '@effect/vitest>effect': '${versions_cjs_namespaceObject.EFFECT_VERSION}'`
380
+ ],
381
+ [
382
+ /^ {2}'@effect\/vitest': .+$/mu,
383
+ ` '@effect/vitest': ${versions_cjs_namespaceObject.EFFECT_VITEST_VERSION}`
384
+ ],
385
+ [
386
+ /^ {2}effect: .+$/mu,
387
+ ` effect: ${versions_cjs_namespaceObject.EFFECT_VERSION}`
388
+ ]
389
+ ];
390
+ for (const [pattern, replacement] of replacements){
391
+ const result = replaceYamlLine(source, pattern, replacement);
392
+ source = result.source;
393
+ changed = result.changed || changed;
394
+ }
395
+ for (const item of strictEffectPackageVersionPolicyExclusions){
396
+ const packageName = item.slice(0, item.lastIndexOf('@'));
397
+ const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
398
+ const currentVersion = replaceYamlLine(source, new RegExp(`^ {2}- '${escapedPackageName}@[^']+'$`, 'gmu'), ` - '${item}'`);
399
+ source = currentVersion.source;
400
+ changed = currentVersion.changed || changed;
401
+ for (const policyKey of [
402
+ 'minimumReleaseAgeExclude',
403
+ 'trustPolicyExclude'
404
+ ]){
405
+ const policyExclude = ensureYamlListItem(source, policyKey, item);
406
+ source = policyExclude.source;
407
+ changed = policyExclude.changed || changed;
408
+ }
409
+ }
410
+ if (changed) external_node_fs_default().writeFileSync(workspaceFile, source, 'utf-8');
411
+ return changed;
412
+ }
413
+ function updateUltramodernConfig(workspaceRoot, packageSource) {
414
+ const configPath = external_node_path_default().join(workspaceRoot, '.modernjs/ultramodern.json');
415
+ const config = readJsonFile(configPath);
416
+ config.packageSource = {
417
+ strategy: packageSource.strategy,
418
+ modernPackageVersion: packageSource.modernPackageVersion,
419
+ ...packageSource.registry ? {
420
+ registry: packageSource.registry
421
+ } : {},
422
+ ...packageSource.aliasScope ? {
423
+ aliasScope: packageSource.aliasScope
424
+ } : {},
425
+ ...packageSource.aliasPackageNamePrefix ? {
426
+ aliasPackageNamePrefix: packageSource.aliasPackageNamePrefix
427
+ } : {}
428
+ };
429
+ for (const app of config.topology?.apps ?? [])if (app && 'object' == typeof app && !Array.isArray(app)) normalizeStrictEffectApiMetadata(app);
430
+ writeJsonFile(configPath, config);
431
+ }
432
+ function updateReferenceTopology(workspaceRoot) {
433
+ const topologyPath = external_node_path_default().join(workspaceRoot, 'topology/reference-topology.json');
434
+ if (!external_node_fs_default().existsSync(topologyPath)) return false;
435
+ const topology = readJsonFile(topologyPath);
436
+ let changed = false;
437
+ for (const vertical of topology.verticals ?? [])if (vertical && 'object' == typeof vertical && !Array.isArray(vertical)) changed = normalizeStrictEffectApiMetadata(vertical) || changed;
438
+ if (changed) writeJsonFile(topologyPath, topology);
439
+ return changed;
440
+ }
441
+ function createMigrationPackageSource(args, current) {
442
+ const strategy = hasFlag(args, '--workspace') ? 'workspace' : 'install';
443
+ const registry = readOption(args, '--registry') ?? readOption(args, '--ultramodern-package-registry');
444
+ const explicitAliasScope = readOption(args, '--alias-scope') ?? readOption(args, '--ultramodern-package-scope');
445
+ const aliasScope = explicitAliasScope ?? ('install' === strategy && void 0 === registry ? current.packageSource?.aliasScope ?? external_ultramodern_package_source_cjs_namespaceObject.BLEEDINGDEV_PACKAGE_SCOPE : current.packageSource?.aliasScope);
446
+ const aliasPackageNamePrefix = readOption(args, '--alias-package-name-prefix') ?? readOption(args, '--ultramodern-package-name-prefix') ?? current.packageSource?.aliasPackageNamePrefix ?? (aliasScope ? external_ultramodern_package_source_cjs_namespaceObject.BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0);
447
+ if ('workspace' === strategy) return {
448
+ strategy,
449
+ modernPackageVersion: external_ultramodern_package_source_cjs_namespaceObject.WORKSPACE_PACKAGE_VERSION,
450
+ ...registry ? {
451
+ registry
452
+ } : {},
453
+ ...aliasScope ? {
454
+ aliasScope
455
+ } : {},
456
+ ...aliasPackageNamePrefix ? {
457
+ aliasPackageNamePrefix
458
+ } : {}
459
+ };
460
+ const version = readOption(args, '--version') ?? readOption(args, '--ultramodern-package-version') ?? current.packageSource?.modernPackageVersion;
461
+ if (!version || version === external_ultramodern_package_source_cjs_namespaceObject.WORKSPACE_PACKAGE_VERSION) throw new Error('migrate-strict-effect needs --version <published-ultramodern-version> for install package source.');
462
+ return {
463
+ strategy,
464
+ modernPackageVersion: version,
465
+ ...registry ? {
466
+ registry
467
+ } : {},
468
+ ...aliasScope ? {
469
+ aliasScope
470
+ } : {},
471
+ ...aliasPackageNamePrefix ? {
472
+ aliasPackageNamePrefix
473
+ } : {}
474
+ };
475
+ }
476
+ function runPnpmLockfileRefresh(context) {
477
+ const result = (0, external_node_child_process_namespaceObject.spawnSync)('pnpm', [
478
+ 'install',
479
+ '--lockfile-only',
480
+ "--ignore-scripts"
481
+ ], {
482
+ cwd: context.workspaceRoot,
483
+ stdio: 'inherit'
484
+ });
485
+ if (result.error) throw result.error;
486
+ return result.status ?? 1;
487
+ }
488
+ function runMigrateStrictEffect(args, context) {
489
+ if (args.includes('--help') || args.includes('-h')) {
490
+ process.stdout.write(`Usage:
491
+ modern-js-create ultramodern migrate-strict-effect --version <version> [--skip-install]
492
+
493
+ Updates generated UltraModern package-source metadata, Modern package aliases,
494
+ framework-owned toolchain pins, direct Effect API topology metadata, strict
495
+ Effect pnpm overrides/trust policy, and the pnpm lockfile. Source code still
496
+ has to pass pnpm api:check and pnpm contract:check.
497
+ `);
498
+ return 0;
499
+ }
500
+ const current = (0, external_config_cjs_namespaceObject.readUltramodernConfig)(context.workspaceRoot);
501
+ const packageSource = createMigrationPackageSource(args, current);
502
+ updateUltramodernConfig(context.workspaceRoot, packageSource);
503
+ updateReferenceTopology(context.workspaceRoot);
504
+ for (const relativePackageFile of listWorkspacePackageFiles(context.workspaceRoot)){
505
+ const packageFile = external_node_path_default().join(context.workspaceRoot, relativePackageFile);
506
+ const packageJson = readJsonFile(packageFile);
507
+ if ('package.json' === relativePackageFile) {
508
+ packageJson.modernjs ??= {};
509
+ packageJson.modernjs.packageSource = {
510
+ strategy: packageSource.strategy,
511
+ config: './.modernjs/ultramodern.json'
512
+ };
513
+ }
514
+ const modernDependenciesChanged = updateModernDependencies(packageJson, packageSource);
515
+ const toolingDependenciesChanged = updateGeneratedToolingDependencies(packageJson);
516
+ const generatedScriptsChanged = updateGeneratedPackageScripts(packageJson);
517
+ const changed = modernDependenciesChanged || toolingDependenciesChanged || generatedScriptsChanged;
518
+ if (changed) writeJsonFile(packageFile, packageJson);
519
+ else if ('package.json' === relativePackageFile) writeJsonFile(packageFile, packageJson);
520
+ }
521
+ updateGeneratedPnpmWorkspacePolicy(context.workspaceRoot);
522
+ if (!hasFlag(args, '--skip-install')) {
523
+ const status = runPnpmLockfileRefresh(context);
524
+ if (0 !== status) return status;
525
+ }
526
+ process.stdout.write(`UltraModern strict Effect metadata migrated to ${packageSource.modernPackageVersion}. Run pnpm api:check && pnpm contract:check next.\n`);
527
+ return 0;
528
+ }
132
529
  function runSkills(args, context) {
133
530
  const [subcommand, ...rest] = args;
134
531
  if ('install' === subcommand) return spawnNodeScript("template-workspace/scripts/bootstrap-agent-skills.mjs", rest, context);
@@ -159,6 +556,8 @@ async function runUltramodernToolingCli(args, workspaceRoot = process.env.ULTRAM
159
556
  });
160
557
  case 'mf-types':
161
558
  return runMfTypes(rest, context);
559
+ case 'migrate-strict-effect':
560
+ return runMigrateStrictEffect(rest, context);
162
561
  case 'public-surface':
163
562
  return spawnNodeScript("templates/workspace-scripts/generate-public-surface-assets.mjs", rest, context);
164
563
  case 'cloudflare-proof':
@@ -289,6 +289,7 @@ function createUltramodernConfig(scope, modernVersion, packageSource, apps = [
289
289
  publicSurface: "scripts/generate-public-surface-assets.mts",
290
290
  cloudflareProof: "scripts/proof-cloudflare-version.mts",
291
291
  performanceReadiness: "scripts/ultramodern-performance-readiness.mts",
292
+ migrateStrictEffect: "scripts/migrate-strict-effect.mts",
292
293
  apiBoundaries: "scripts/check-ultramodern-api-boundaries.mts",
293
294
  skills: "scripts/bootstrap-agent-skills.mts"
294
295
  }
@@ -144,6 +144,8 @@ ${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 buildCacheTarget = cloudflareDeployEnabled ? 'cloudflare' : 'web';
148
+ const buildCacheDirectory = \`node_modules/.cache/rspack-\${appId}-\${buildCacheTarget}\`;
147
149
 
148
150
  if (
149
151
  cloudflareDeployEnabled &&
@@ -190,6 +192,10 @@ ${bffConfig} ...(cloudflareDeployEnabled
190
192
  splitRouteChunks: true,
191
193
  },
192
194
  performance: {
195
+ buildCache: {
196
+ cacheDigest: [appId, buildCacheTarget],
197
+ cacheDirectory: buildCacheDirectory,
198
+ },
193
199
  rsdoctor: {
194
200
  disableClientServer: true,
195
201
  enabled: process.env['ULTRAMODERN_RSDOCTOR'] === 'true',
@@ -224,6 +224,7 @@ function createRootPackageJson(scope, packageSource, remotes = [], bridge) {
224
224
  'agents:refs:check': "node ./scripts/setup-agent-reference-repos.mts --check",
225
225
  'mf:types': "node ./scripts/assert-mf-types.mts",
226
226
  'performance:readiness': "node ./scripts/ultramodern-performance-readiness.mts",
227
+ 'migrate:strict-effect': "node ./scripts/migrate-strict-effect.mts",
227
228
  'contract:check': "node ./scripts/validate-ultramodern-workspace.mts",
228
229
  'api:check': "node ./scripts/check-ultramodern-api-boundaries.mts",
229
230
  'i18n:boundaries': "node ./scripts/check-ultramodern-i18n-boundaries.mts",
@@ -416,7 +417,7 @@ function createAppPackage(scope, app, packageSource, enableTailwind, remotes = [
416
417
  scripts: {
417
418
  dev: 'modern dev',
418
419
  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}`,
419
- 'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build && ${publicSurfaceCloudflareBuildCommand} && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy && ${publicSurfaceCloudflareOutputCommand}`,
420
+ 'cloudflare:build': `ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern build && ${publicSurfaceCloudflareBuildCommand} && ULTRAMODERN_ZEPHYR=false MODERNJS_DEPLOY=cloudflare modern deploy --skip-build && ${publicSurfaceCloudflareOutputCommand}`,
420
421
  'cloudflare:deploy': 'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS=true pnpm run cloudflare:build && wrangler deploy --config .output/wrangler.json',
421
422
  'cloudflare:preview': 'pnpm run cloudflare:build && wrangler dev --config .output/wrangler.json',
422
423
  'cloudflare:proof': `node ${(0, external_naming_cjs_namespaceObject.relativeRootFor)(app.directory)}/scripts/proof-cloudflare-version.mts --app ${app.id}`,
@@ -37,12 +37,14 @@ const CLOUDFLARE_COMPATIBILITY_DATE = '2026-06-02';
37
37
  const TAILWIND_VERSION = '4.3.1';
38
38
  const TAILWIND_POSTCSS_VERSION = '4.3.1';
39
39
  const POSTCSS_VERSION = '8.5.15';
40
+ const EFFECT_VERSION = '4.0.0-beta.91';
41
+ const EFFECT_VITEST_VERSION = '4.0.0-beta.91';
40
42
  const EFFECT_TSGO_VERSION = '0.14.6';
41
43
  const TYPESCRIPT_STABLE_VERSION = '6.0.3';
42
- const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260624.1';
44
+ const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260628.1';
43
45
  const TYPESCRIPT_VERSION = TYPESCRIPT_STABLE_VERSION;
44
46
  const OXLINT_VERSION = '1.71.0';
45
- const OXFMT_VERSION = '0.55.0';
47
+ const OXFMT_VERSION = '0.56.0';
46
48
  const ULTRACITE_VERSION = '7.8.3';
47
49
  const LEFTHOOK_VERSION = '^2.1.9';
48
50
  const I18NEXT_VERSION = '26.3.1';
@@ -60,12 +62,16 @@ const ultramodernWorkspaceVersions = {
60
62
  tanstackRouter: TANSTACK_ROUTER_VERSION,
61
63
  tanstackRouterCore: TANSTACK_ROUTER_CORE_VERSION,
62
64
  moduleFederation: MODULE_FEDERATION_VERSION,
65
+ effect: EFFECT_VERSION,
66
+ effectVitest: EFFECT_VITEST_VERSION,
63
67
  tailwind: TAILWIND_VERSION,
64
68
  tailwindPostcss: TAILWIND_POSTCSS_VERSION
65
69
  };
66
70
  __webpack_require__.d(__webpack_exports__, {}, {
67
71
  CLOUDFLARE_COMPATIBILITY_DATE: CLOUDFLARE_COMPATIBILITY_DATE,
68
72
  EFFECT_TSGO_VERSION: EFFECT_TSGO_VERSION,
73
+ EFFECT_VERSION: EFFECT_VERSION,
74
+ EFFECT_VITEST_VERSION: EFFECT_VITEST_VERSION,
69
75
  I18NEXT_VERSION: I18NEXT_VERSION,
70
76
  LEFTHOOK_VERSION: LEFTHOOK_VERSION,
71
77
  MODULE_FEDERATION_AGENT_SKILLS_COMMIT: MODULE_FEDERATION_AGENT_SKILLS_COMMIT,
@@ -97,6 +103,8 @@ __webpack_require__.d(__webpack_exports__, {}, {
97
103
  });
98
104
  exports.CLOUDFLARE_COMPATIBILITY_DATE = __webpack_exports__.CLOUDFLARE_COMPATIBILITY_DATE;
99
105
  exports.EFFECT_TSGO_VERSION = __webpack_exports__.EFFECT_TSGO_VERSION;
106
+ exports.EFFECT_VERSION = __webpack_exports__.EFFECT_VERSION;
107
+ exports.EFFECT_VITEST_VERSION = __webpack_exports__.EFFECT_VITEST_VERSION;
100
108
  exports.I18NEXT_VERSION = __webpack_exports__.I18NEXT_VERSION;
101
109
  exports.LEFTHOOK_VERSION = __webpack_exports__.LEFTHOOK_VERSION;
102
110
  exports.MODULE_FEDERATION_AGENT_SKILLS_COMMIT = __webpack_exports__.MODULE_FEDERATION_AGENT_SKILLS_COMMIT;
@@ -128,6 +136,8 @@ exports.ultramodernWorkspaceVersions = __webpack_exports__.ultramodernWorkspaceV
128
136
  for(var __rspack_i in __webpack_exports__)if (-1 === [
129
137
  "CLOUDFLARE_COMPATIBILITY_DATE",
130
138
  "EFFECT_TSGO_VERSION",
139
+ "EFFECT_VERSION",
140
+ "EFFECT_VITEST_VERSION",
131
141
  "I18NEXT_VERSION",
132
142
  "LEFTHOOK_VERSION",
133
143
  "MODULE_FEDERATION_AGENT_SKILLS_COMMIT",
@@ -209,6 +209,7 @@ function writeGeneratedWorkspaceScripts(targetDir, _scope, _enableTailwind, _rem
209
209
  writeWorkspaceOwnedMtsScript(targetDir, 'proof-cloudflare-version', createToolWrapperScript('cloudflare-proof'));
210
210
  (0, external_fs_io_cjs_namespaceObject.writeFileReplacing)(targetDir, "scripts/ultramodern-performance-readiness.config.mjs", createPerformanceReadinessConfigScript());
211
211
  writeWorkspaceOwnedMtsScript(targetDir, 'ultramodern-performance-readiness', createToolWrapperScript('performance-readiness'));
212
+ writeWorkspaceOwnedMtsScript(targetDir, 'migrate-strict-effect', createToolWrapperScript('migrate-strict-effect'));
212
213
  writeWorkspaceOwnedMtsScript(targetDir, 'ultramodern-typecheck', createToolWrapperScript('typecheck'));
213
214
  writeWorkspaceOwnedMtsScript(targetDir, 'bootstrap-agent-skills', createSkillsToolWrapperScript());
214
215
  migrateCopiedWorkspaceScriptToMts(targetDir, 'setup-agent-reference-repos');
@@ -175,6 +175,8 @@ function generateUltramodernWorkspace(options) {
175
175
  nodeVersion: external_versions_cjs_namespaceObject.NODE_VERSION,
176
176
  pnpmVersion: external_versions_cjs_namespaceObject.PNPM_VERSION,
177
177
  nodeFetchVersion: external_versions_cjs_namespaceObject.NODE_FETCH_VERSION,
178
+ effectVersion: external_versions_cjs_namespaceObject.EFFECT_VERSION,
179
+ effectVitestVersion: external_versions_cjs_namespaceObject.EFFECT_VITEST_VERSION,
178
180
  tanstackRouterCoreVersion: external_versions_cjs_namespaceObject.TANSTACK_ROUTER_CORE_VERSION,
179
181
  tanstackRouterVersion: external_versions_cjs_namespaceObject.TANSTACK_ROUTER_VERSION,
180
182
  typescriptVersion: external_versions_cjs_namespaceObject.TYPESCRIPT_VERSION,