@bleedingdev/modern-js-ultramodern-create 3.9.0-ultramodern.3 → 3.9.0-ultramodern.4

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 (48) hide show
  1. package/dist/cjs/ultramodern-package-source.cjs +2 -1
  2. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-build-identity.cjs +5 -2
  3. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-modern-configs.cjs +5 -0
  4. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.cjs +28 -9
  5. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/pnpm-policy.cjs +9 -13
  6. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.cjs +30 -7
  7. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.cjs +13 -5
  8. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/workspace-artifact-ownership.cjs +215 -0
  9. package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect.cjs +70 -8
  10. package/dist/cjs/ultramodern-workspace/module-federation/reexport-module.cjs +18 -46
  11. package/dist/cjs/ultramodern-workspace/package-json.cjs +1 -0
  12. package/dist/cjs/ultramodern-workspace/workspace-validation-contract.cjs +2 -1
  13. package/dist/cjs/ultramodern-workspace/write-app.cjs +1 -1
  14. package/dist/esm/ultramodern-package-source.js +2 -1
  15. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-build-identity.js +5 -2
  16. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-modern-configs.js +5 -0
  17. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.js +28 -9
  18. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/pnpm-policy.js +9 -13
  19. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.js +30 -7
  20. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.js +13 -5
  21. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/workspace-artifact-ownership.js +166 -0
  22. package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect.js +71 -9
  23. package/dist/esm/ultramodern-workspace/module-federation/reexport-module.js +18 -46
  24. package/dist/esm/ultramodern-workspace/package-json.js +1 -0
  25. package/dist/esm/ultramodern-workspace/workspace-validation-contract.js +2 -1
  26. package/dist/esm/ultramodern-workspace/write-app.js +1 -1
  27. package/dist/esm-node/ultramodern-package-source.js +2 -1
  28. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-build-identity.js +5 -2
  29. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-modern-configs.js +5 -0
  30. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.js +28 -9
  31. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/pnpm-policy.js +9 -13
  32. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.js +30 -7
  33. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.js +13 -5
  34. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/workspace-artifact-ownership.js +167 -0
  35. package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect.js +71 -9
  36. package/dist/esm-node/ultramodern-workspace/module-federation/reexport-module.js +18 -46
  37. package/dist/esm-node/ultramodern-workspace/package-json.js +1 -0
  38. package/dist/esm-node/ultramodern-workspace/workspace-validation-contract.js +2 -1
  39. package/dist/esm-node/ultramodern-workspace/write-app.js +1 -1
  40. package/dist/types/ultramodern-package-source.d.ts +1 -1
  41. package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.d.ts +3 -1
  42. package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.d.ts +7 -0
  43. package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/workspace-artifact-ownership.d.ts +27 -0
  44. package/dist/types/ultramodern-workspace/module-federation/reexport-module.d.ts +2 -2
  45. package/dist/types/ultramodern-workspace/workspace-validation-contract.d.ts +1 -1
  46. package/package.json +5 -4
  47. package/template-workspace/.modernjs/release-cohort.json +40 -40
  48. package/template-workspace/scripts/bootstrap-agent-skills.mjs +4 -4
@@ -44,11 +44,13 @@ var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node
44
44
  const external_node_path_namespaceObject = require("node:path");
45
45
  var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
46
46
  const external_ultramodern_release_cohort_cjs_namespaceObject = require("../../ultramodern-release-cohort.cjs");
47
+ const app_files_cjs_namespaceObject = require("../../ultramodern-workspace/app-files.cjs");
47
48
  const contracts_cjs_namespaceObject = require("../../ultramodern-workspace/contracts.cjs");
48
49
  const delivery_unit_stamp_cjs_namespaceObject = require("../../ultramodern-workspace/delivery-unit-stamp.cjs");
49
50
  const policy_cjs_namespaceObject = require("../../ultramodern-workspace/policy.cjs");
50
51
  const shells_cjs_namespaceObject = require("../../ultramodern-workspace/shells.cjs");
51
52
  const workspace_scripts_cjs_namespaceObject = require("../../ultramodern-workspace/workspace-scripts.cjs");
53
+ const zerops_cjs_namespaceObject = require("../../ultramodern-workspace/zerops.cjs");
52
54
  const external_config_cjs_namespaceObject = require("../config.cjs");
53
55
  const api_metadata_cjs_namespaceObject = require("./migrate-strict-effect/api-metadata.cjs");
54
56
  const declaration_patches_cjs_namespaceObject = require("./migrate-strict-effect/declaration-patches.cjs");
@@ -63,6 +65,7 @@ const pnpm_policy_cjs_namespaceObject = require("./migrate-strict-effect/pnpm-po
63
65
  const react_router_retirement_cjs_namespaceObject = require("./migrate-strict-effect/react-router-retirement.cjs");
64
66
  const shared_api_infrastructure_cjs_namespaceObject = require("./migrate-strict-effect/shared-api-infrastructure.cjs");
65
67
  const toolchain_pins_cjs_namespaceObject = require("./migrate-strict-effect/toolchain-pins.cjs");
68
+ const workspace_artifact_ownership_cjs_namespaceObject = require("./migrate-strict-effect/workspace-artifact-ownership.cjs");
66
69
  const external_options_cjs_namespaceObject = require("./options.cjs");
67
70
  const retiredMetadataPaths = [
68
71
  '.modernjs/ultramodern-generated-contract.json',
@@ -118,10 +121,24 @@ function synchronizeMigrationDeliveryUnitMetadata(io, raw, packageSource) {
118
121
  'schemaVersion',
119
122
  'id',
120
123
  "description",
121
- 'preset',
122
- 'sharedPackages',
123
- 'validation'
124
- ])topology[key] = canonicalTopology[key];
124
+ 'preset'
125
+ ])if ('id' === key || "description" === key) topology[key] ??= canonicalTopology[key];
126
+ else topology[key] = canonicalTopology[key];
127
+ const existingSharedPackages = Array.isArray(topology.sharedPackages) ? topology.sharedPackages : [];
128
+ topology.sharedPackages = [
129
+ ...existingSharedPackages,
130
+ ...canonicalTopology.sharedPackages.filter((candidate)=>!existingSharedPackages.some((existing)=>existing.id === candidate.id))
131
+ ];
132
+ topology.validation = {
133
+ ...canonicalTopology.validation,
134
+ ...topology.validation,
135
+ commands: [
136
+ ...new Set([
137
+ ...topology.validation?.commands ?? [],
138
+ ...canonicalTopology.validation.commands
139
+ ])
140
+ ]
141
+ };
125
142
  const canonicalTopologyApps = new Map([
126
143
  canonicalTopology.shell,
127
144
  ...canonicalTopology.verticals ?? []
@@ -144,8 +161,21 @@ function synchronizeMigrationDeliveryUnitMetadata(io, raw, packageSource) {
144
161
  'api',
145
162
  'cloudflare',
146
163
  'ownership'
147
- ])if (Object.hasOwn(canonicalEntry, key)) entry[key] = canonicalEntry[key];
148
- else delete entry[key];
164
+ ])if (Object.hasOwn(canonicalEntry, key)) {
165
+ const canonicalValue = canonicalEntry[key];
166
+ if ('api' === key && entry.api && canonicalValue && 'object' == typeof canonicalValue) {
167
+ const nextApi = {
168
+ ...entry.api,
169
+ ...canonicalValue
170
+ };
171
+ if (!Object.hasOwn(entry.api, 'domainOperations')) delete nextApi.domainOperations;
172
+ entry.api = nextApi;
173
+ } else if ('cloudflare' === key && entry.cloudflare && canonicalValue && 'object' == typeof canonicalValue) entry.cloudflare = {
174
+ ...canonicalValue,
175
+ ...entry.cloudflare
176
+ };
177
+ else entry[key] = canonicalValue;
178
+ } else delete entry[key];
149
179
  }
150
180
  }
151
181
  (0, io_cjs_namespaceObject.writeJsonFile)(io, topologyPath, topology);
@@ -166,7 +196,10 @@ function synchronizeMigrationCompactPolicy(io, raw, packageSource) {
166
196
  const apps = (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)(migrated);
167
197
  apps.filter((app)=>'shell' !== app.kind);
168
198
  const canonical = requireRecord((0, contracts_cjs_namespaceObject.createUltramodernConfig)(migrated.workspace.packageScope, packageSource.modernPackageVersion, packageSource, apps, migrated.features.tailwind, migrated.bridge, (0, external_config_cjs_namespaceObject.additionalShellsFromToolingConfig)(migrated), apps.find((app)=>'shell' === app.kind)), 'Generated compact policy');
169
- for (const key of compactPolicyKeys)raw[key] = canonical[key];
199
+ for (const key of compactPolicyKeys){
200
+ if ('workspace' === key) canonical.workspace.packageManager.version = raw.workspace.packageManager.version;
201
+ raw[key] = canonical[key];
202
+ }
170
203
  (0, io_cjs_namespaceObject.writeJsonFile)(io, external_node_path_default().join(io.workspaceRoot, '.modernjs/ultramodern.json'), raw);
171
204
  }
172
205
  function reconcileRootPackageSourceMetadata(packageJson, packageSource) {
@@ -306,6 +339,33 @@ function migrateStrictEffect(args, context, io, dryRun, skipInstall) {
306
339
  version: packageSource.modernPackageVersion
307
340
  });
308
341
  const releaseCohort = 'install' === packageSource.strategy ? (0, external_ultramodern_release_cohort_cjs_namespaceObject.readCreateReleaseCohort)() : void 0;
342
+ const currentApps = (0, external_config_cjs_namespaceObject.workspaceAppsFromToolingConfig)(current);
343
+ const allCurrentApps = (0, external_config_cjs_namespaceObject.allWorkspaceAppsFromToolingConfig)(current);
344
+ const artifactOwnership = (0, workspace_artifact_ownership_cjs_namespaceObject.preserveConsumerWorkspaceArtifacts)(io, [
345
+ ...allCurrentApps.map((app)=>({
346
+ relativePath: `${app.directory}/src/modern-app-env.d.ts`,
347
+ content: (0, app_files_cjs_namespaceObject.createAppEnvDts)(app, allCurrentApps.filter((remote)=>'shell' !== remote.kind), current.workspace.packageScope)
348
+ })),
349
+ ...(0, workspace_scripts_cjs_namespaceObject.migratedWorkspaceScriptArtifacts)({
350
+ shellOnly: false,
351
+ hasBackendSurface: true
352
+ }).filter((artifact)=>"scripts/validate-ultramodern-workspace.mts" !== artifact.relativePath),
353
+ {
354
+ relativePath: "scripts/validate-ultramodern-workspace.mts",
355
+ legacyPath: "scripts/validate-ultramodern-workspace.mjs",
356
+ generatedDataBinding: 'workspaceValidationContract',
357
+ content: (0, workspace_scripts_cjs_namespaceObject.createWorkspaceValidationScript)(current.workspace.packageScope, current.features.tailwind, currentApps.filter((app)=>'shell' !== app.kind), void 0, (0, external_config_cjs_namespaceObject.additionalShellsFromToolingConfig)(current), currentApps.find((app)=>'shell' === app.kind))
358
+ },
359
+ {
360
+ relativePath: 'zerops.yaml',
361
+ content: `${(0, zerops_cjs_namespaceObject.createZeropsYaml)(current.workspace.packageScope, (0, external_config_cjs_namespaceObject.allWorkspaceAppsFromToolingConfig)(current))}\n`
362
+ },
363
+ {
364
+ relativePath: "scripts/materialize-zerops-runtime.mjs",
365
+ content: (0, workspace_scripts_cjs_namespaceObject.createZeropsRuntimeMaterializationScript)()
366
+ }
367
+ ]);
368
+ io = artifactOwnership.io;
309
369
  (0, api_metadata_cjs_namespaceObject.reconcileCompactPackageSourceMetadata)(raw.packageSource, packageSource);
310
370
  reconcileRootPackageSourceMetadata((0, io_cjs_namespaceObject.readJsonFile)(external_node_path_default().join(io.workspaceRoot, 'package.json')), packageSource);
311
371
  (0, pnpm_policy_cjs_namespaceObject.updateGeneratedPnpmWorkspacePolicy)((0, io_cjs_namespaceObject.createMigrationIo)(io.workspaceRoot, true), packageSource, {
@@ -357,6 +417,7 @@ function migrateStrictEffect(args, context, io, dryRun, skipInstall) {
357
417
  io.writeGenerated(external_node_path_default().join(io.workspaceRoot, artifact.relativePath), artifact.content);
358
418
  }
359
419
  io.writeGenerated(external_node_path_default().join(io.workspaceRoot, "scripts/validate-ultramodern-workspace.mts"), (0, workspace_scripts_cjs_namespaceObject.createWorkspaceValidationScript)(validationContractInputs.scope, validationContractInputs.enableTailwind, validationContractInputs.remotes, releaseCohort, validationContractInputs.additionalShells, validationContractInputs.primaryShell, raw, external_node_fs_default().existsSync(external_node_path_default().join(io.workspaceRoot, 'topology/ownership.json')) ? requireRecord((0, io_cjs_namespaceObject.readJsonFile)(external_node_path_default().join(io.workspaceRoot, 'topology/ownership.json')), 'Ownership topology') : void 0, developmentOverlay));
420
+ artifactOwnership.refreshReleaseCohort(releaseCohort);
360
421
  for (const relativePath of retiredMetadataPaths)io.remove(external_node_path_default().join(io.workspaceRoot, relativePath));
361
422
  (0, generated_artifacts_cjs_namespaceObject.updateGeneratedBuildIdentityModules)(io, migrated);
362
423
  (0, generated_artifacts_cjs_namespaceObject.updateGeneratedTypeScriptSurfaces)(io, migrated);
@@ -371,7 +432,7 @@ function migrateStrictEffect(args, context, io, dryRun, skipInstall) {
371
432
  reconcileRootPackageSourceMetadata(packageJson, packageSource);
372
433
  (0, toolchain_pins_cjs_namespaceObject.updateRootPackageToolchain)(packageJson);
373
434
  }
374
- (0, package_cohort_cjs_namespaceObject.updateModernDependencies)(packageJson, packageSource);
435
+ (0, package_cohort_cjs_namespaceObject.updateModernDependencies)(packageJson, packageSource, releaseCohort);
375
436
  const ownsGeneratedScripts = 'package.json' === relativePackageFile || allMigratedApps.some((app)=>`${app.directory}/package.json` === relativePackageFile);
376
437
  (0, package_cohort_cjs_namespaceObject.updateGeneratedToolingDependencies)(packageJson, {
377
438
  ownsGeneratedScripts
@@ -381,6 +442,7 @@ function migrateStrictEffect(args, context, io, dryRun, skipInstall) {
381
442
  if ('preserved' === retiredReactRouter) io.log(`${relativePackageFile} keeps its react-router dependency: authored source imports React Router directly, so its generated Module Federation config keeps bridge.enableBridgeRouter: true.`);
382
443
  else if ('removed' === retiredReactRouter) io.log(`${relativePackageFile} dropped its obsolete react-router dependency: no authored source imports React Router.`);
383
444
  (0, package_cohort_cjs_namespaceObject.updateGeneratedPackageScripts)(packageJson, {
445
+ preservedArtifacts: artifactOwnership.preservedPaths,
384
446
  relativePackageFile,
385
447
  apps: allMigratedApps,
386
448
  shellOnly,
@@ -34,6 +34,7 @@ __webpack_require__.d(__webpack_exports__, {
34
34
  });
35
35
  const universal_namespaceObject = require("@modern-js/utils/universal");
36
36
  const external_delivery_unit_cjs_namespaceObject = require("../delivery-unit.cjs");
37
+ const external_descriptors_cjs_namespaceObject = require("../descriptors.cjs");
37
38
  function deliveryUnitRecordFor(scope, app) {
38
39
  return app.deliveryUnit ? app.deliveryUnit : (0, external_delivery_unit_cjs_namespaceObject.createDeliveryUnitRecord)(scope, app);
39
40
  }
@@ -41,57 +42,28 @@ function createUltramodernBuildArtifactJson(scope, app) {
41
42
  const record = deliveryUnitRecordFor(scope, app);
42
43
  return `${JSON.stringify((0, universal_namespaceObject.createUltramodernBuildArtifact)(record), null, 2)}\n`;
43
44
  }
44
- function createUltramodernBuildModule(scope, app) {
45
+ function createUltramodernBuildModule(scope, app, includeUiMarker = (0, external_descriptors_cjs_namespaceObject.appEmitsBrowserUi)(app)) {
45
46
  const record = deliveryUnitRecordFor(scope, app);
46
- return `declare const ULTRAMODERN_BUILD_MARKER: string;
47
+ return `import { resolveUltramodernBuildArtifact } from '@modern-js/runtime-extensions/build-identity';
48
+
49
+ declare const ULTRAMODERN_BUILD_MARKER: string;
47
50
  declare const ULTRAMODERN_SOURCE_REVISION: string;
48
51
 
49
- const ultramodernGeneratedBuildArtifact = ${JSON.stringify((0, universal_namespaceObject.createUltramodernBuildArtifact)(record), null, 2)} as const;
50
- const ultramodernBuildMarker =
51
- typeof ULTRAMODERN_BUILD_MARKER === 'string'
52
- ? ULTRAMODERN_BUILD_MARKER
53
- : ultramodernGeneratedBuildArtifact.deliveryUnit.buildMarker;
54
- const ultramodernSourceRevision =
55
- typeof ULTRAMODERN_SOURCE_REVISION === 'string'
56
- ? ULTRAMODERN_SOURCE_REVISION
57
- : ultramodernGeneratedBuildArtifact.deliveryUnit.sourceRevision;
58
- const ultramodernBuildArtifact = {
59
- ...ultramodernGeneratedBuildArtifact,
60
- deliveryUnit: {
61
- ...ultramodernGeneratedBuildArtifact.deliveryUnit,
62
- build: ultramodernBuildMarker,
63
- buildMarker: ultramodernBuildMarker,
64
- sourceRevision: ultramodernSourceRevision,
65
- },
66
- surfaces: {
67
- api: {
68
- ...ultramodernGeneratedBuildArtifact.surfaces.api,
69
- build: ultramodernBuildMarker,
70
- buildMarker: ultramodernBuildMarker,
71
- sourceRevision: ultramodernSourceRevision,
72
- },
73
- ui: {
74
- ...ultramodernGeneratedBuildArtifact.surfaces.ui,
75
- build: ultramodernBuildMarker,
76
- buildMarker: ultramodernBuildMarker,
77
- sourceRevision: ultramodernSourceRevision,
78
- },
79
- },
80
- } as const;
52
+ const ultramodernBuildArtifact = resolveUltramodernBuildArtifact(${JSON.stringify((0, universal_namespaceObject.createUltramodernBuildArtifact)(record), null, 2)} as const, {
53
+ buildMarker: () => ULTRAMODERN_BUILD_MARKER,
54
+ sourceRevision: () => ULTRAMODERN_SOURCE_REVISION,
55
+ });
81
56
 
82
- export const ultramodernDeliveryUnit =
83
- ultramodernBuildArtifact.deliveryUnit;
84
- export const ultramodernUiMarker = ultramodernBuildArtifact.surfaces.ui;
85
- export const ultramodernApiMarker = ultramodernBuildArtifact.surfaces.api;
86
- `;
57
+ export const ultramodernDeliveryUnit = ultramodernBuildArtifact.deliveryUnit;
58
+ ${includeUiMarker ? 'export const ultramodernUiMarker = ultramodernBuildArtifact.surfaces.ui;\n' : ''}${'shell' !== app.kind && (0, external_descriptors_cjs_namespaceObject.appHasApi)(app) ? 'export const ultramodernApiMarker = ultramodernBuildArtifact.surfaces.api;\n' : ''}`;
87
59
  }
88
- function createUltramodernBuildReexportModule() {
89
- return `export {
90
- ultramodernApiMarker,
91
- ultramodernDeliveryUnit,
92
- ultramodernUiMarker,
93
- } from '../shared/ultramodern-build';
94
- `;
60
+ function createUltramodernBuildReexportModule(app, includeUiMarker = (0, external_descriptors_cjs_namespaceObject.appEmitsBrowserUi)(app)) {
61
+ const names = [
62
+ 'ultramodernDeliveryUnit'
63
+ ];
64
+ if (includeUiMarker) names.push('ultramodernUiMarker');
65
+ if ('shell' !== app.kind && (0, external_descriptors_cjs_namespaceObject.appHasApi)(app)) names.push('ultramodernApiMarker');
66
+ return `export { ${names.join(', ')} } from '../shared/ultramodern-build';\n`;
95
67
  }
96
68
  exports.createUltramodernBuildArtifactJson = __webpack_exports__.createUltramodernBuildArtifactJson;
97
69
  exports.createUltramodernBuildModule = __webpack_exports__.createUltramodernBuildModule;
@@ -51,6 +51,7 @@ function appDependencies(scope, packageSource, app, remotes = [], bridge) {
51
51
  const dependencies = {
52
52
  '@modern-js/plugin-tanstack': (0, external_ultramodern_package_source_cjs_namespaceObject.modernPackageSpecifier)('@modern-js/plugin-tanstack', packageSource),
53
53
  '@modern-js/plugin-i18n': (0, external_ultramodern_package_source_cjs_namespaceObject.modernPackageSpecifier)('@modern-js/plugin-i18n', packageSource),
54
+ '@modern-js/runtime-extensions': (0, external_ultramodern_package_source_cjs_namespaceObject.modernPackageSpecifier)('@modern-js/runtime-extensions', packageSource),
54
55
  '@modern-js/runtime': (0, external_ultramodern_package_source_cjs_namespaceObject.modernPackageSpecifier)('@modern-js/runtime', packageSource),
55
56
  ...external_policy_cjs_namespaceObject.ULTRAMODERN_PACKAGE_PINS.appDependencies,
56
57
  [(0, external_naming_cjs_namespaceObject.packageName)(scope, 'shared-contracts')]: external_ultramodern_package_source_cjs_namespaceObject.WORKSPACE_PACKAGE_VERSION,
@@ -55,7 +55,8 @@ const modernPackageCohort = [
55
55
  '@modern-js/plugin-bff',
56
56
  '@modern-js/plugin-i18n',
57
57
  '@modern-js/plugin-tanstack',
58
- '@modern-js/runtime'
58
+ '@modern-js/runtime',
59
+ '@modern-js/runtime-extensions'
59
60
  ];
60
61
  const asJsonRecord = (value)=>value;
61
62
  function projectModuleFederationMetadata(value) {
@@ -78,7 +78,7 @@ function writeAppConfigFiles({ targetDir, scope, resolvedApp, packageSource, ena
78
78
  (0, external_fs_io_cjs_namespaceObject.writeJson)(targetDir, `${resolvedApp.directory}/tsconfig.json`, (0, external_package_json_cjs_namespaceObject.createAppTsConfig)(resolvedApp, remotes));
79
79
  (0, external_fs_io_cjs_namespaceObject.writeJson)(targetDir, `${resolvedApp.directory}/tsconfig.mf-types.json`, (0, external_package_json_cjs_namespaceObject.createAppMfTypesTsConfig)(resolvedApp));
80
80
  (0, external_fs_io_cjs_namespaceObject.writeFile)(targetDir, `${resolvedApp.directory}/src/modern-app-env.d.ts`, (0, external_app_files_cjs_namespaceObject.createAppEnvDts)(resolvedApp, remotes, scope));
81
- (0, external_fs_io_cjs_namespaceObject.writeFile)(targetDir, `${resolvedApp.directory}/src/ultramodern-build.ts`, (0, external_module_federation_cjs_namespaceObject.createUltramodernBuildReexportModule)());
81
+ if ('api-only' !== resolvedApp.surfaceProfile) (0, external_fs_io_cjs_namespaceObject.writeFile)(targetDir, `${resolvedApp.directory}/src/ultramodern-build.ts`, (0, external_module_federation_cjs_namespaceObject.createUltramodernBuildReexportModule)(resolvedApp));
82
82
  (0, external_fs_io_cjs_namespaceObject.writeFile)(targetDir, `${resolvedApp.directory}/shared/ultramodern-build.ts`, (0, external_module_federation_cjs_namespaceObject.createUltramodernBuildModule)(scope, resolvedApp));
83
83
  (0, external_fs_io_cjs_namespaceObject.writeFile)(targetDir, `${resolvedApp.directory}/shared/ultramodern-build.json`, (0, external_module_federation_cjs_namespaceObject.createUltramodernBuildArtifactJson)(scope, resolvedApp));
84
84
  if (emitsUi) {
@@ -24,7 +24,8 @@ const ULTRAMODERN_WORKSPACE_MODERN_PACKAGES = [
24
24
  '@modern-js/plugin-bff',
25
25
  '@modern-js/plugin-i18n',
26
26
  '@modern-js/plugin-tanstack',
27
- '@modern-js/runtime'
27
+ '@modern-js/runtime',
28
+ '@modern-js/runtime-extensions'
28
29
  ];
29
30
  function modernPackageVersion(packageSource) {
30
31
  return 'install' === packageSource.strategy ? packageSource.modernPackageVersion : WORKSPACE_PACKAGE_VERSION;
@@ -1,5 +1,6 @@
1
1
  import node_fs from "node:fs";
2
2
  import node_path from "node:path";
3
+ import { appEmitsBrowserUi } from "../../../ultramodern-workspace/descriptors.js";
3
4
  import { createUltramodernBuildArtifactJson, createUltramodernBuildModule, createUltramodernBuildReexportModule } from "../../../ultramodern-workspace/module-federation.js";
4
5
  import { allWorkspaceAppsFromToolingConfig } from "../../config.js";
5
6
  const legacyApiMarkerPattern = /export const ultramodernApiMarker\s*=\s*\{[\s\S]*?\}\s+as const;\n?/u;
@@ -39,8 +40,10 @@ function updateGeneratedBuildIdentityModules(io, config) {
39
40
  for (const app of allWorkspaceAppsFromToolingConfig(config)){
40
41
  const sharedApiPath = node_path.join(io.workspaceRoot, app.directory, 'shared/api.ts');
41
42
  if (app.api && node_fs.existsSync(sharedApiPath)) io.write(sharedApiPath, rewriteApiMarkerIdentitySchema(rewriteLegacyApiMarkerBinding(node_fs.readFileSync(sharedApiPath, 'utf-8'))));
42
- io.writeGenerated(node_path.join(io.workspaceRoot, app.directory, 'src/ultramodern-build.ts'), createUltramodernBuildReexportModule());
43
- io.writeGenerated(node_path.join(io.workspaceRoot, app.directory, 'shared/ultramodern-build.ts'), createUltramodernBuildModule(config.workspace.packageScope, app));
43
+ const reexportPath = node_path.join(io.workspaceRoot, app.directory, 'src/ultramodern-build.ts');
44
+ const includeUiMarker = appEmitsBrowserUi(app) && ('shell' !== app.kind || node_fs.existsSync(reexportPath));
45
+ if (node_fs.existsSync(reexportPath)) io.writeGenerated(reexportPath, createUltramodernBuildReexportModule(app, includeUiMarker));
46
+ io.writeGenerated(node_path.join(io.workspaceRoot, app.directory, 'shared/ultramodern-build.ts'), createUltramodernBuildModule(config.workspace.packageScope, app, includeUiMarker));
44
47
  io.write(node_path.join(io.workspaceRoot, app.directory, 'shared/ultramodern-build.json'), createUltramodernBuildArtifactJson(config.workspace.packageScope, app));
45
48
  }
46
49
  }
@@ -117,6 +117,7 @@ function updateGeneratedModernConfigs(io, config) {
117
117
  generatedModuleFederationConfig,
118
118
  createGeneratedModuleFederationConfig(!enableBridgeRouter)
119
119
  ];
120
+ const ownsUiComposition = !node_fs.existsSync(moduleFederationConfigPath) || recognizedModuleFederationConfigs.includes(node_fs.readFileSync(moduleFederationConfigPath, 'utf8'));
120
121
  if (appEmitsBrowserUi(app)) writeOwnedTypeScriptConfig(io, moduleFederationConfigPath, generatedModuleFederationConfig, recognizedModuleFederationConfigs);
121
122
  else removeOwnedTypeScriptConfig(io, moduleFederationConfigPath, recognizedModuleFederationConfigs);
122
123
  const backendFederationConfigPath = node_path.join(io.workspaceRoot, app.directory, 'backend-federation.config.ts');
@@ -127,6 +128,10 @@ function updateGeneratedModernConfigs(io, config) {
127
128
  else removeOwnedTypeScriptConfig(io, backendFederationConfigPath, [
128
129
  generatedBackendFederationConfig
129
130
  ]);
131
+ if (!ownsUiComposition) {
132
+ io.log(`${app.directory} preserves its consumer-owned federation composition instead of regenerating routes from unproven metadata.`);
133
+ continue;
134
+ }
130
135
  if ('shell' === app.kind) {
131
136
  const shellUiRemotes = resolveRemoteRefs(app, remotes).filter(appEmitsBrowserUi);
132
137
  const componentsPath = node_path.join(io.workspaceRoot, app.directory, 'src/routes/vertical-components.tsx');
@@ -24,13 +24,20 @@ function updateDeclaredDependencies(packageJson, pins) {
24
24
  }
25
25
  return changed;
26
26
  }
27
- function updateModernDependencies(packageJson, packageSource) {
27
+ function updateModernDependencies(packageJson, packageSource, releaseCohort) {
28
28
  let changed = false;
29
29
  for (const section of [
30
30
  'dependencies',
31
31
  'devDependencies'
32
32
  ]){
33
33
  const dependencies = packageJson[section];
34
+ if (dependencies && Object.hasOwn(dependencies, '@modern-js/runtime')) {
35
+ const runtimeExtensions = modernPackageSpecifier('@modern-js/runtime-extensions', packageSource);
36
+ if (dependencies['@modern-js/runtime-extensions'] !== runtimeExtensions) {
37
+ dependencies['@modern-js/runtime-extensions'] = runtimeExtensions;
38
+ changed = true;
39
+ }
40
+ }
34
41
  if (dependencies && Object.hasOwn(dependencies, '@modern-js/create')) {
35
42
  dependencies[ULTRAMODERN_CREATE_PACKAGE] = modernPackageSpecifier(ULTRAMODERN_CREATE_PACKAGE, packageSource);
36
43
  delete dependencies['@modern-js/create'];
@@ -38,11 +45,23 @@ function updateModernDependencies(packageJson, packageSource) {
38
45
  }
39
46
  }
40
47
  return updateDeclaredDependencies(packageJson, new Map([
41
- ...modernPackageNames
42
- ].map((packageName)=>[
43
- packageName,
44
- modernPackageSpecifier(packageName, packageSource)
45
- ]))) || changed;
48
+ ...[
49
+ ...modernPackageNames
50
+ ].map((packageName)=>[
51
+ packageName,
52
+ modernPackageSpecifier(packageName, packageSource)
53
+ ]),
54
+ ...(releaseCohort?.packages ?? []).flatMap((item)=>[
55
+ [
56
+ item.sourceName,
57
+ modernPackageSpecifier(item.sourceName, packageSource)
58
+ ],
59
+ [
60
+ item.targetName,
61
+ item.version
62
+ ]
63
+ ])
64
+ ])) || changed;
46
65
  }
47
66
  const generatedToolingDependencyPins = new Map(Object.entries({
48
67
  ...ULTRAMODERN_PACKAGE_PINS.appDependencies,
@@ -189,12 +208,12 @@ function mergeGeneratedScript(consumer, framework, canRetireLegacyOxfmtCliExclus
189
208
  preservedConsumerSegments: consumerExtras.length > 0
190
209
  };
191
210
  }
192
- function rewriteMigratedScriptReferences(scripts) {
211
+ function rewriteMigratedScriptReferences(scripts, preservedArtifacts) {
193
212
  let changed = false;
194
213
  const pattern = new RegExp(`(scripts/(?:${migratedWorkspaceScriptBasenames.join('|')}))\\.mjs`, 'gu');
195
214
  for (const [name, value] of Object.entries(scripts)){
196
215
  if ('string' != typeof value) continue;
197
- const next = value.replace(pattern, '$1.mts');
216
+ const next = value.replace(pattern, (original, basename)=>preservedArtifacts?.has(`${basename}.mjs`) ? original : `${basename}.mts`);
198
217
  if (next !== value) {
199
218
  scripts[name] = next;
200
219
  changed = true;
@@ -209,7 +228,7 @@ function updateGeneratedPackageScripts(packageJson, options = {}) {
209
228
  const apps = options.apps ?? [];
210
229
  const app = apps.find((candidate)=>`${candidate.directory}/package.json` === options.relativePackageFile);
211
230
  const isRootPackage = 'package.json' === options.relativePackageFile;
212
- if (rewriteMigratedScriptReferences(scripts)) changed = true;
231
+ if (rewriteMigratedScriptReferences(scripts, options.preservedArtifacts)) changed = true;
213
232
  if (isRootPackage) {
214
233
  for (const [name, [legacy, portable]] of legacyPortableRootScripts)if (true === options.canRetireLegacyOxfmtCliExclusion && scripts[name] === legacy) {
215
234
  scripts[name] = portable;
@@ -199,11 +199,7 @@ function reconcilePatchedDependencies(document, includeDrizzleOrmPatch) {
199
199
  patchKey(patch),
200
200
  patch
201
201
  ]));
202
- const ownedPackageNames = new Set([
203
- ...policy.required,
204
- ...policy.conditional,
205
- ...policy.stale
206
- ].map((patch)=>patch.packageName));
202
+ const ownedPackageNames = new Set(expectedPatches.map((patch)=>patch.packageName));
207
203
  const patchedDependencies = ensureMap(document, 'patchedDependencies');
208
204
  for (const [selector, patchPath] of Object.entries(patchedDependencies)){
209
205
  const stalePatch = stale.get(selector);
@@ -212,15 +208,13 @@ function reconcilePatchedDependencies(document, includeDrizzleOrmPatch) {
212
208
  delete patchedDependencies[selector];
213
209
  continue;
214
210
  }
215
- const parts = packageVersionParts(selector);
216
- if (parts && ownedPackageNames.has(parts.packageName) && !expected.has(selector)) {
217
- const conditionalPatch = policy.conditional.find((patch)=>patchKey(patch) === selector);
218
- if (conditionalPatch && !includeDrizzleOrmPatch && patchPath === conditionalPatch.path) {
219
- delete patchedDependencies[selector];
220
- continue;
221
- }
222
- throw new Error(`Framework-owned patch selector ${selector} has unknown provenance.`);
211
+ const conditionalPatch = policy.conditional.find((patch)=>patchKey(patch) === selector);
212
+ if (conditionalPatch && !includeDrizzleOrmPatch && patchPath === conditionalPatch.path) {
213
+ delete patchedDependencies[selector];
214
+ continue;
223
215
  }
216
+ const parts = packageVersionParts(selector);
217
+ if (parts && ownedPackageNames.has(parts.packageName) && !expected.has(selector)) throw new Error(`Framework-owned patch selector ${selector} has unknown provenance.`);
224
218
  }
225
219
  for (const [selector, patchPath] of expected)patchedDependencies[selector] = patchPath;
226
220
  }
@@ -511,6 +505,8 @@ async function validateGeneratedPnpmLockReleaseAgePolicy(workspaceRoot, packageS
511
505
  const firstPartyTargetNames = new Set(releaseCohort?.packages.map((item)=>item.targetName) ?? []);
512
506
  const { document: lockfile } = parsePnpmWorkspaceYaml(node_fs.readFileSync(lockfilePath, 'utf-8'), lockfilePath);
513
507
  const closure = discoverReachablePnpmLockReleaseAgeClosure(lockfile);
508
+ const firstPartySourceNames = new Set(releaseCohort?.packages.map((item)=>item.sourceName) ?? []);
509
+ for (const tarball of closure.tarballs)if (firstPartyTargetNames.has(tarball.packageName) || firstPartySourceNames.has(tarball.packageName)) throw new Error(`First-party lock candidate ${tarball.packageName} must resolve through the authenticated release cohort, not a tarball URL.`);
514
510
  if (closure.unresolved.length > 0) {
515
511
  const unresolved = closure.unresolved.slice(0, 20).map((candidate)=>{
516
512
  const packageName = candidate.package ?? 'unknown package';
@@ -9,6 +9,11 @@ const integrityPattern = /^sha512-[A-Za-z0-9+/]+={0,2}$/u;
9
9
  function isExactSemver(version) {
10
10
  return semver.valid(version) === version;
11
11
  }
12
+ function isHttpsTarballLocator(value) {
13
+ if (!value.startsWith('https://') || /[\s()]/u.test(value) || !URL.canParse(value)) return false;
14
+ const url = new URL(value);
15
+ return url.href === value && '' === url.username && '' === url.password && '' === url.hash;
16
+ }
12
17
  function isYamlRecord(value) {
13
18
  return Boolean(value) && 'object' == typeof value && !Array.isArray(value);
14
19
  }
@@ -62,7 +67,7 @@ function splitPeerContext(locator) {
62
67
  for (const segment of segments){
63
68
  if (/^patch_hash=[a-f0-9]{32,128}$/u.test(segment) || /^[a-f0-9]{32,128}$/u.test(segment)) continue;
64
69
  const peer = parsePackageKey(segment);
65
- if (!peer) return {
70
+ if (!peer || isHttpsTarballLocator(peer.version)) return {
66
71
  unresolved: locator
67
72
  };
68
73
  peers.push(peer);
@@ -74,11 +79,12 @@ function splitPeerContext(locator) {
74
79
  }
75
80
  function parsePackageLocator(rawLocator) {
76
81
  const locator = rawLocator.replace(/^\//u, '');
77
- const separator = locator.lastIndexOf('@');
82
+ const tarballSeparator = locator.indexOf('@https://');
83
+ const separator = tarballSeparator > 0 ? tarballSeparator : locator.lastIndexOf('@');
78
84
  if (separator <= 0) return;
79
85
  const packageName = locator.slice(0, separator);
80
86
  const version = locator.slice(separator + 1);
81
- if (!exactPackageNamePattern.test(packageName) || !isExactSemver(version)) return;
87
+ if (!exactPackageNamePattern.test(packageName) || !isExactSemver(version) && !isHttpsTarballLocator(version)) return;
82
88
  return {
83
89
  packageName,
84
90
  version,
@@ -122,6 +128,11 @@ function dependencyIdentity(dependencyName, rawValue) {
122
128
  const peerContext = splitPeerContext(value.startsWith('npm:') ? value.slice(4) : value);
123
129
  if ('unresolved' in peerContext) return peerContext;
124
130
  const { base, peers } = peerContext;
131
+ if (isHttpsTarballLocator(base) && exactPackageNamePattern.test(dependencyName)) return {
132
+ packageName: dependencyName,
133
+ version: base,
134
+ peers
135
+ };
125
136
  const full = parsePackageLocator(base);
126
137
  if (full) return {
127
138
  ...full,
@@ -264,13 +275,11 @@ function discoverReachablePnpmLockReleaseAgeClosure(lockfile) {
264
275
  const currentPath = shortestIdentityPaths.get(key);
265
276
  if (!currentPath || nodePath.length < currentPath.length) shortestIdentityPaths.set(key, nodePath);
266
277
  }
278
+ const tarballs = [];
267
279
  const candidates = [
268
280
  ...shortestIdentityPaths.entries()
269
281
  ].map(([key, path])=>{
270
- const [packageName, version] = [
271
- key.slice(0, key.lastIndexOf('@')),
272
- key.slice(key.lastIndexOf('@') + 1)
273
- ];
282
+ const { packageName, version } = nodes.get(nodeIdsByIdentity.get(key)[0]).identity;
274
283
  const packageRecordsForIdentity = packageRecordsByIdentity.get(key);
275
284
  if (!packageRecordsForIdentity?.length) return void recordUnresolved({
276
285
  packageName,
@@ -278,12 +287,25 @@ function discoverReachablePnpmLockReleaseAgeClosure(lockfile) {
278
287
  peers: []
279
288
  }, path, 'missing exact SHA-512 lock integrity');
280
289
  let integrity;
290
+ let tarballVersion;
281
291
  for (const [packageKey, packageRecord] of packageRecordsForIdentity){
282
292
  const resolution = requiredYamlRecord(requiredYamlRecord(packageRecord, `pnpm lockfile package ${packageKey}`).resolution, `pnpm lockfile package ${packageKey} resolution`);
283
293
  if ('string' != typeof resolution.integrity || !integrityPattern.test(resolution.integrity)) throw new Error(`pnpm lockfile package ${packageKey} has uncertain registry integrity.`);
284
294
  if (integrity && integrity !== resolution.integrity) throw new Error(`pnpm lockfile has conflicting registry integrity for ${key}.`);
285
295
  integrity = resolution.integrity;
296
+ if (isHttpsTarballLocator(version)) {
297
+ const metadata = requiredYamlRecord(packageRecord, `pnpm lockfile package ${packageKey}`);
298
+ if (resolution.tarball !== version || 'string' != typeof metadata.version || !isExactSemver(metadata.version) || void 0 !== tarballVersion && tarballVersion !== metadata.version) throw new Error(`pnpm lockfile package ${packageKey} has uncertain tarball identity.`);
299
+ tarballVersion = metadata.version;
300
+ }
286
301
  }
302
+ if (void 0 !== tarballVersion) return void tarballs.push({
303
+ packageName,
304
+ version: tarballVersion,
305
+ url: version,
306
+ integrity: integrity,
307
+ path
308
+ });
287
309
  return {
288
310
  packageName,
289
311
  version,
@@ -298,6 +320,7 @@ function discoverReachablePnpmLockReleaseAgeClosure(lockfile) {
298
320
  unresolved.sort((left, right)=>JSON.stringify(left).localeCompare(JSON.stringify(right)));
299
321
  return {
300
322
  candidates,
323
+ tarballs,
301
324
  unresolved
302
325
  };
303
326
  }
@@ -1,10 +1,15 @@
1
1
  import node_fs from "node:fs";
2
2
  import node_path from "node:path";
3
+ import { semver } from "@modern-js/utils";
3
4
  import { ULTRAMODERN_PACKAGE_PINS, ULTRAMODERN_WORKSPACE_POLICY } from "../../../ultramodern-workspace/policy.js";
4
5
  const { toolchain: toolchain } = ULTRAMODERN_WORKSPACE_POLICY;
5
6
  const retiredRootToolingDependencies = [
6
7
  "@typescript/typescript6"
7
8
  ];
9
+ function migrationPnpmVersion(value) {
10
+ const baseline = toolchain.packageManager.version;
11
+ return 'string' == typeof value && semver.valid(value) && semver.major(value) === semver.major(baseline) && semver.gte(value, baseline) ? value : baseline;
12
+ }
8
13
  function isRecord(value) {
9
14
  return Boolean(value) && 'object' == typeof value && !Array.isArray(value);
10
15
  }
@@ -22,13 +27,14 @@ function updateUltramodernConfigToolchain(config) {
22
27
  const workspace = ensureRecord(config, 'workspace', 'workspace');
23
28
  const packageManager = ensureRecord(workspace, 'packageManager', 'workspace.packageManager');
24
29
  packageManager.name = toolchain.packageManager.name;
25
- packageManager.version = toolchain.packageManager.version;
30
+ packageManager.version = migrationPnpmVersion(packageManager.version);
26
31
  const node = ensureRecord(workspace, 'node', 'workspace.node');
27
32
  node.version = toolchain.node.version;
28
33
  node.engineRange = toolchain.node.engineRange;
29
34
  }
30
35
  function updateRootPackageToolchain(packageJson) {
31
- packageJson.packageManager = `${toolchain.packageManager.name}@${toolchain.packageManager.version}`;
36
+ const currentVersion = 'string' == typeof packageJson.packageManager ? packageJson.packageManager.match(/^pnpm@([^+]+)(?:\+.*)?$/u)?.[1] : void 0;
37
+ packageJson.packageManager = `${toolchain.packageManager.name}@${migrationPnpmVersion(currentVersion)}`;
32
38
  const engines = ensureRecord(packageJson, 'engines', 'package.json engines');
33
39
  engines.node = toolchain.node.engineRange;
34
40
  engines.pnpm = toolchain.packageManager.engineRange;
@@ -38,7 +44,7 @@ function updateRootPackageToolchain(packageJson) {
38
44
  devDependencies['@types/node'] = ULTRAMODERN_PACKAGE_PINS.rootDevDependencies["@types/node"];
39
45
  devDependencies.miniflare = ULTRAMODERN_PACKAGE_PINS.rootDevDependencies.miniflare;
40
46
  }
41
- function updateMiseTools(content) {
47
+ function updateMiseTools(content, pnpmVersion) {
42
48
  const lines = content.replace(/\r\n/gu, '\n').split('\n');
43
49
  if ('' === lines.at(-1)) lines.pop();
44
50
  let toolsStart = lines.findIndex((line)=>/^\s*\[tools\]\s*(?:#.*)?$/u.test(line));
@@ -65,13 +71,15 @@ function updateMiseTools(content) {
65
71
  lines[index] = line;
66
72
  };
67
73
  upsertTool('node', toolchain.node.version);
68
- upsertTool('pnpm', toolchain.packageManager.version);
74
+ upsertTool('pnpm', pnpmVersion);
69
75
  return `${lines.join('\n')}\n`;
70
76
  }
71
77
  function updateGeneratedToolchainFiles(io) {
72
78
  const misePath = node_path.join(io.workspaceRoot, '.mise.toml');
73
79
  const miseContent = node_fs.existsSync(misePath) ? node_fs.readFileSync(misePath, 'utf-8') : '';
74
- io.write(misePath, updateMiseTools(miseContent));
80
+ const packageJson = JSON.parse(node_fs.readFileSync(node_path.join(io.workspaceRoot, 'package.json'), 'utf8'));
81
+ const pnpmVersion = migrationPnpmVersion(packageJson.packageManager?.match(/^pnpm@([^+]+)(?:\+.*)?$/u)?.[1]);
82
+ io.write(misePath, updateMiseTools(miseContent, pnpmVersion));
75
83
  const workflowPath = node_path.join(io.workspaceRoot, '.github/workflows/ultramodern-workspace-gates.yml');
76
84
  if (!node_fs.existsSync(workflowPath)) return;
77
85
  const workflow = node_fs.readFileSync(workflowPath, 'utf-8');