@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.
- package/dist/cjs/ultramodern-package-source.cjs +2 -1
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-build-identity.cjs +5 -2
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-modern-configs.cjs +5 -0
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.cjs +28 -9
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/pnpm-policy.cjs +9 -13
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.cjs +30 -7
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.cjs +13 -5
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/workspace-artifact-ownership.cjs +215 -0
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect.cjs +70 -8
- package/dist/cjs/ultramodern-workspace/module-federation/reexport-module.cjs +18 -46
- package/dist/cjs/ultramodern-workspace/package-json.cjs +1 -0
- package/dist/cjs/ultramodern-workspace/workspace-validation-contract.cjs +2 -1
- package/dist/cjs/ultramodern-workspace/write-app.cjs +1 -1
- package/dist/esm/ultramodern-package-source.js +2 -1
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-build-identity.js +5 -2
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-modern-configs.js +5 -0
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.js +28 -9
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/pnpm-policy.js +9 -13
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.js +30 -7
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.js +13 -5
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/workspace-artifact-ownership.js +166 -0
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect.js +71 -9
- package/dist/esm/ultramodern-workspace/module-federation/reexport-module.js +18 -46
- package/dist/esm/ultramodern-workspace/package-json.js +1 -0
- package/dist/esm/ultramodern-workspace/workspace-validation-contract.js +2 -1
- package/dist/esm/ultramodern-workspace/write-app.js +1 -1
- package/dist/esm-node/ultramodern-package-source.js +2 -1
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-build-identity.js +5 -2
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-modern-configs.js +5 -0
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.js +28 -9
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/pnpm-policy.js +9 -13
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.js +30 -7
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.js +13 -5
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/workspace-artifact-ownership.js +167 -0
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect.js +71 -9
- package/dist/esm-node/ultramodern-workspace/module-federation/reexport-module.js +18 -46
- package/dist/esm-node/ultramodern-workspace/package-json.js +1 -0
- package/dist/esm-node/ultramodern-workspace/workspace-validation-contract.js +2 -1
- package/dist/esm-node/ultramodern-workspace/write-app.js +1 -1
- package/dist/types/ultramodern-package-source.d.ts +1 -1
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.d.ts +3 -1
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.d.ts +7 -0
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/workspace-artifact-ownership.d.ts +27 -0
- package/dist/types/ultramodern-workspace/module-federation/reexport-module.d.ts +2 -2
- package/dist/types/ultramodern-workspace/workspace-validation-contract.d.ts +1 -1
- package/package.json +5 -4
- package/template-workspace/.modernjs/release-cohort.json +40 -40
- package/template-workspace/scripts/bootstrap-agent-skills.mjs +4 -4
|
@@ -53,7 +53,8 @@ const ULTRAMODERN_WORKSPACE_MODERN_PACKAGES = [
|
|
|
53
53
|
'@modern-js/plugin-bff',
|
|
54
54
|
'@modern-js/plugin-i18n',
|
|
55
55
|
'@modern-js/plugin-tanstack',
|
|
56
|
-
'@modern-js/runtime'
|
|
56
|
+
'@modern-js/runtime',
|
|
57
|
+
'@modern-js/runtime-extensions'
|
|
57
58
|
];
|
|
58
59
|
function modernPackageVersion(packageSource) {
|
|
59
60
|
return 'install' === packageSource.strategy ? packageSource.modernPackageVersion : WORKSPACE_PACKAGE_VERSION;
|
|
@@ -45,6 +45,7 @@ const external_node_fs_namespaceObject = require("node:fs");
|
|
|
45
45
|
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
|
|
46
46
|
const external_node_path_namespaceObject = require("node:path");
|
|
47
47
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
48
|
+
const descriptors_cjs_namespaceObject = require("../../../ultramodern-workspace/descriptors.cjs");
|
|
48
49
|
const module_federation_cjs_namespaceObject = require("../../../ultramodern-workspace/module-federation.cjs");
|
|
49
50
|
const external_config_cjs_namespaceObject = require("../../config.cjs");
|
|
50
51
|
const legacyApiMarkerPattern = /export const ultramodernApiMarker\s*=\s*\{[\s\S]*?\}\s+as const;\n?/u;
|
|
@@ -84,8 +85,10 @@ function updateGeneratedBuildIdentityModules(io, config) {
|
|
|
84
85
|
for (const app of (0, external_config_cjs_namespaceObject.allWorkspaceAppsFromToolingConfig)(config)){
|
|
85
86
|
const sharedApiPath = external_node_path_default().join(io.workspaceRoot, app.directory, 'shared/api.ts');
|
|
86
87
|
if (app.api && external_node_fs_default().existsSync(sharedApiPath)) io.write(sharedApiPath, rewriteApiMarkerIdentitySchema(rewriteLegacyApiMarkerBinding(external_node_fs_default().readFileSync(sharedApiPath, 'utf-8'))));
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
const reexportPath = external_node_path_default().join(io.workspaceRoot, app.directory, 'src/ultramodern-build.ts');
|
|
89
|
+
const includeUiMarker = (0, descriptors_cjs_namespaceObject.appEmitsBrowserUi)(app) && ('shell' !== app.kind || external_node_fs_default().existsSync(reexportPath));
|
|
90
|
+
if (external_node_fs_default().existsSync(reexportPath)) io.writeGenerated(reexportPath, (0, module_federation_cjs_namespaceObject.createUltramodernBuildReexportModule)(app, includeUiMarker));
|
|
91
|
+
io.writeGenerated(external_node_path_default().join(io.workspaceRoot, app.directory, 'shared/ultramodern-build.ts'), (0, module_federation_cjs_namespaceObject.createUltramodernBuildModule)(config.workspace.packageScope, app, includeUiMarker));
|
|
89
92
|
io.write(external_node_path_default().join(io.workspaceRoot, app.directory, 'shared/ultramodern-build.json'), (0, module_federation_cjs_namespaceObject.createUltramodernBuildArtifactJson)(config.workspace.packageScope, app));
|
|
90
93
|
}
|
|
91
94
|
}
|
|
@@ -160,6 +160,7 @@ function updateGeneratedModernConfigs(io, config) {
|
|
|
160
160
|
generatedModuleFederationConfig,
|
|
161
161
|
createGeneratedModuleFederationConfig(!enableBridgeRouter)
|
|
162
162
|
];
|
|
163
|
+
const ownsUiComposition = !external_node_fs_default().existsSync(moduleFederationConfigPath) || recognizedModuleFederationConfigs.includes(external_node_fs_default().readFileSync(moduleFederationConfigPath, 'utf8'));
|
|
163
164
|
if ((0, descriptors_cjs_namespaceObject.appEmitsBrowserUi)(app)) writeOwnedTypeScriptConfig(io, moduleFederationConfigPath, generatedModuleFederationConfig, recognizedModuleFederationConfigs);
|
|
164
165
|
else removeOwnedTypeScriptConfig(io, moduleFederationConfigPath, recognizedModuleFederationConfigs);
|
|
165
166
|
const backendFederationConfigPath = external_node_path_default().join(io.workspaceRoot, app.directory, 'backend-federation.config.ts');
|
|
@@ -170,6 +171,10 @@ function updateGeneratedModernConfigs(io, config) {
|
|
|
170
171
|
else removeOwnedTypeScriptConfig(io, backendFederationConfigPath, [
|
|
171
172
|
generatedBackendFederationConfig
|
|
172
173
|
]);
|
|
174
|
+
if (!ownsUiComposition) {
|
|
175
|
+
io.log(`${app.directory} preserves its consumer-owned federation composition instead of regenerating routes from unproven metadata.`);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
173
178
|
if ('shell' === app.kind) {
|
|
174
179
|
const shellUiRemotes = (0, descriptors_cjs_namespaceObject.resolveRemoteRefs)(app, remotes).filter(descriptors_cjs_namespaceObject.appEmitsBrowserUi);
|
|
175
180
|
const componentsPath = external_node_path_default().join(io.workspaceRoot, app.directory, 'src/routes/vertical-components.tsx');
|
|
@@ -59,13 +59,20 @@ function updateDeclaredDependencies(packageJson, pins) {
|
|
|
59
59
|
}
|
|
60
60
|
return changed;
|
|
61
61
|
}
|
|
62
|
-
function updateModernDependencies(packageJson, packageSource) {
|
|
62
|
+
function updateModernDependencies(packageJson, packageSource, releaseCohort) {
|
|
63
63
|
let changed = false;
|
|
64
64
|
for (const section of [
|
|
65
65
|
'dependencies',
|
|
66
66
|
'devDependencies'
|
|
67
67
|
]){
|
|
68
68
|
const dependencies = packageJson[section];
|
|
69
|
+
if (dependencies && Object.hasOwn(dependencies, '@modern-js/runtime')) {
|
|
70
|
+
const runtimeExtensions = (0, external_ultramodern_package_source_cjs_namespaceObject.modernPackageSpecifier)('@modern-js/runtime-extensions', packageSource);
|
|
71
|
+
if (dependencies['@modern-js/runtime-extensions'] !== runtimeExtensions) {
|
|
72
|
+
dependencies['@modern-js/runtime-extensions'] = runtimeExtensions;
|
|
73
|
+
changed = true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
69
76
|
if (dependencies && Object.hasOwn(dependencies, '@modern-js/create')) {
|
|
70
77
|
dependencies[external_ultramodern_package_source_cjs_namespaceObject.ULTRAMODERN_CREATE_PACKAGE] = (0, external_ultramodern_package_source_cjs_namespaceObject.modernPackageSpecifier)(external_ultramodern_package_source_cjs_namespaceObject.ULTRAMODERN_CREATE_PACKAGE, packageSource);
|
|
71
78
|
delete dependencies['@modern-js/create'];
|
|
@@ -73,11 +80,23 @@ function updateModernDependencies(packageJson, packageSource) {
|
|
|
73
80
|
}
|
|
74
81
|
}
|
|
75
82
|
return updateDeclaredDependencies(packageJson, new Map([
|
|
76
|
-
...
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
83
|
+
...[
|
|
84
|
+
...modernPackageNames
|
|
85
|
+
].map((packageName)=>[
|
|
86
|
+
packageName,
|
|
87
|
+
(0, external_ultramodern_package_source_cjs_namespaceObject.modernPackageSpecifier)(packageName, packageSource)
|
|
88
|
+
]),
|
|
89
|
+
...(releaseCohort?.packages ?? []).flatMap((item)=>[
|
|
90
|
+
[
|
|
91
|
+
item.sourceName,
|
|
92
|
+
(0, external_ultramodern_package_source_cjs_namespaceObject.modernPackageSpecifier)(item.sourceName, packageSource)
|
|
93
|
+
],
|
|
94
|
+
[
|
|
95
|
+
item.targetName,
|
|
96
|
+
item.version
|
|
97
|
+
]
|
|
98
|
+
])
|
|
99
|
+
])) || changed;
|
|
81
100
|
}
|
|
82
101
|
const generatedToolingDependencyPins = new Map(Object.entries({
|
|
83
102
|
...policy_cjs_namespaceObject.ULTRAMODERN_PACKAGE_PINS.appDependencies,
|
|
@@ -224,12 +243,12 @@ function mergeGeneratedScript(consumer, framework, canRetireLegacyOxfmtCliExclus
|
|
|
224
243
|
preservedConsumerSegments: consumerExtras.length > 0
|
|
225
244
|
};
|
|
226
245
|
}
|
|
227
|
-
function rewriteMigratedScriptReferences(scripts) {
|
|
246
|
+
function rewriteMigratedScriptReferences(scripts, preservedArtifacts) {
|
|
228
247
|
let changed = false;
|
|
229
248
|
const pattern = new RegExp(`(scripts/(?:${workspace_scripts_cjs_namespaceObject.migratedWorkspaceScriptBasenames.join('|')}))\\.mjs`, 'gu');
|
|
230
249
|
for (const [name, value] of Object.entries(scripts)){
|
|
231
250
|
if ('string' != typeof value) continue;
|
|
232
|
-
const next = value.replace(pattern,
|
|
251
|
+
const next = value.replace(pattern, (original, basename)=>preservedArtifacts?.has(`${basename}.mjs`) ? original : `${basename}.mts`);
|
|
233
252
|
if (next !== value) {
|
|
234
253
|
scripts[name] = next;
|
|
235
254
|
changed = true;
|
|
@@ -244,7 +263,7 @@ function updateGeneratedPackageScripts(packageJson, options = {}) {
|
|
|
244
263
|
const apps = options.apps ?? [];
|
|
245
264
|
const app = apps.find((candidate)=>`${candidate.directory}/package.json` === options.relativePackageFile);
|
|
246
265
|
const isRootPackage = 'package.json' === options.relativePackageFile;
|
|
247
|
-
if (rewriteMigratedScriptReferences(scripts)) changed = true;
|
|
266
|
+
if (rewriteMigratedScriptReferences(scripts, options.preservedArtifacts)) changed = true;
|
|
248
267
|
if (isRootPackage) {
|
|
249
268
|
for (const [name, [legacy, portable]] of legacyPortableRootScripts)if (true === options.canRetireLegacyOxfmtCliExclusion && scripts[name] === legacy) {
|
|
250
269
|
scripts[name] = portable;
|
|
@@ -244,11 +244,7 @@ function reconcilePatchedDependencies(document, includeDrizzleOrmPatch) {
|
|
|
244
244
|
patchKey(patch),
|
|
245
245
|
patch
|
|
246
246
|
]));
|
|
247
|
-
const ownedPackageNames = new Set(
|
|
248
|
-
...policy.required,
|
|
249
|
-
...policy.conditional,
|
|
250
|
-
...policy.stale
|
|
251
|
-
].map((patch)=>patch.packageName));
|
|
247
|
+
const ownedPackageNames = new Set(expectedPatches.map((patch)=>patch.packageName));
|
|
252
248
|
const patchedDependencies = ensureMap(document, 'patchedDependencies');
|
|
253
249
|
for (const [selector, patchPath] of Object.entries(patchedDependencies)){
|
|
254
250
|
const stalePatch = stale.get(selector);
|
|
@@ -257,15 +253,13 @@ function reconcilePatchedDependencies(document, includeDrizzleOrmPatch) {
|
|
|
257
253
|
delete patchedDependencies[selector];
|
|
258
254
|
continue;
|
|
259
255
|
}
|
|
260
|
-
const
|
|
261
|
-
if (
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
delete patchedDependencies[selector];
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
throw new Error(`Framework-owned patch selector ${selector} has unknown provenance.`);
|
|
256
|
+
const conditionalPatch = policy.conditional.find((patch)=>patchKey(patch) === selector);
|
|
257
|
+
if (conditionalPatch && !includeDrizzleOrmPatch && patchPath === conditionalPatch.path) {
|
|
258
|
+
delete patchedDependencies[selector];
|
|
259
|
+
continue;
|
|
268
260
|
}
|
|
261
|
+
const parts = packageVersionParts(selector);
|
|
262
|
+
if (parts && ownedPackageNames.has(parts.packageName) && !expected.has(selector)) throw new Error(`Framework-owned patch selector ${selector} has unknown provenance.`);
|
|
269
263
|
}
|
|
270
264
|
for (const [selector, patchPath] of expected)patchedDependencies[selector] = patchPath;
|
|
271
265
|
}
|
|
@@ -556,6 +550,8 @@ async function validateGeneratedPnpmLockReleaseAgePolicy(workspaceRoot, packageS
|
|
|
556
550
|
const firstPartyTargetNames = new Set(releaseCohort?.packages.map((item)=>item.targetName) ?? []);
|
|
557
551
|
const { document: lockfile } = (0, external_pnpm_yaml_cjs_namespaceObject.parsePnpmWorkspaceYaml)(external_node_fs_default().readFileSync(lockfilePath, 'utf-8'), lockfilePath);
|
|
558
552
|
const closure = (0, external_pnpm_yaml_cjs_namespaceObject.discoverReachablePnpmLockReleaseAgeClosure)(lockfile);
|
|
553
|
+
const firstPartySourceNames = new Set(releaseCohort?.packages.map((item)=>item.sourceName) ?? []);
|
|
554
|
+
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.`);
|
|
559
555
|
if (closure.unresolved.length > 0) {
|
|
560
556
|
const unresolved = closure.unresolved.slice(0, 20).map((candidate)=>{
|
|
561
557
|
const packageName = candidate.package ?? 'unknown package';
|
|
@@ -44,6 +44,11 @@ const integrityPattern = /^sha512-[A-Za-z0-9+/]+={0,2}$/u;
|
|
|
44
44
|
function isExactSemver(version) {
|
|
45
45
|
return utils_namespaceObject.semver.valid(version) === version;
|
|
46
46
|
}
|
|
47
|
+
function isHttpsTarballLocator(value) {
|
|
48
|
+
if (!value.startsWith('https://') || /[\s()]/u.test(value) || !URL.canParse(value)) return false;
|
|
49
|
+
const url = new URL(value);
|
|
50
|
+
return url.href === value && '' === url.username && '' === url.password && '' === url.hash;
|
|
51
|
+
}
|
|
47
52
|
function isYamlRecord(value) {
|
|
48
53
|
return Boolean(value) && 'object' == typeof value && !Array.isArray(value);
|
|
49
54
|
}
|
|
@@ -97,7 +102,7 @@ function splitPeerContext(locator) {
|
|
|
97
102
|
for (const segment of segments){
|
|
98
103
|
if (/^patch_hash=[a-f0-9]{32,128}$/u.test(segment) || /^[a-f0-9]{32,128}$/u.test(segment)) continue;
|
|
99
104
|
const peer = parsePackageKey(segment);
|
|
100
|
-
if (!peer) return {
|
|
105
|
+
if (!peer || isHttpsTarballLocator(peer.version)) return {
|
|
101
106
|
unresolved: locator
|
|
102
107
|
};
|
|
103
108
|
peers.push(peer);
|
|
@@ -109,11 +114,12 @@ function splitPeerContext(locator) {
|
|
|
109
114
|
}
|
|
110
115
|
function parsePackageLocator(rawLocator) {
|
|
111
116
|
const locator = rawLocator.replace(/^\//u, '');
|
|
112
|
-
const
|
|
117
|
+
const tarballSeparator = locator.indexOf('@https://');
|
|
118
|
+
const separator = tarballSeparator > 0 ? tarballSeparator : locator.lastIndexOf('@');
|
|
113
119
|
if (separator <= 0) return;
|
|
114
120
|
const packageName = locator.slice(0, separator);
|
|
115
121
|
const version = locator.slice(separator + 1);
|
|
116
|
-
if (!exactPackageNamePattern.test(packageName) || !isExactSemver(version)) return;
|
|
122
|
+
if (!exactPackageNamePattern.test(packageName) || !isExactSemver(version) && !isHttpsTarballLocator(version)) return;
|
|
117
123
|
return {
|
|
118
124
|
packageName,
|
|
119
125
|
version,
|
|
@@ -157,6 +163,11 @@ function dependencyIdentity(dependencyName, rawValue) {
|
|
|
157
163
|
const peerContext = splitPeerContext(value.startsWith('npm:') ? value.slice(4) : value);
|
|
158
164
|
if ('unresolved' in peerContext) return peerContext;
|
|
159
165
|
const { base, peers } = peerContext;
|
|
166
|
+
if (isHttpsTarballLocator(base) && exactPackageNamePattern.test(dependencyName)) return {
|
|
167
|
+
packageName: dependencyName,
|
|
168
|
+
version: base,
|
|
169
|
+
peers
|
|
170
|
+
};
|
|
160
171
|
const full = parsePackageLocator(base);
|
|
161
172
|
if (full) return {
|
|
162
173
|
...full,
|
|
@@ -299,13 +310,11 @@ function discoverReachablePnpmLockReleaseAgeClosure(lockfile) {
|
|
|
299
310
|
const currentPath = shortestIdentityPaths.get(key);
|
|
300
311
|
if (!currentPath || nodePath.length < currentPath.length) shortestIdentityPaths.set(key, nodePath);
|
|
301
312
|
}
|
|
313
|
+
const tarballs = [];
|
|
302
314
|
const candidates = [
|
|
303
315
|
...shortestIdentityPaths.entries()
|
|
304
316
|
].map(([key, path])=>{
|
|
305
|
-
const
|
|
306
|
-
key.slice(0, key.lastIndexOf('@')),
|
|
307
|
-
key.slice(key.lastIndexOf('@') + 1)
|
|
308
|
-
];
|
|
317
|
+
const { packageName, version } = nodes.get(nodeIdsByIdentity.get(key)[0]).identity;
|
|
309
318
|
const packageRecordsForIdentity = packageRecordsByIdentity.get(key);
|
|
310
319
|
if (!packageRecordsForIdentity?.length) return void recordUnresolved({
|
|
311
320
|
packageName,
|
|
@@ -313,12 +322,25 @@ function discoverReachablePnpmLockReleaseAgeClosure(lockfile) {
|
|
|
313
322
|
peers: []
|
|
314
323
|
}, path, 'missing exact SHA-512 lock integrity');
|
|
315
324
|
let integrity;
|
|
325
|
+
let tarballVersion;
|
|
316
326
|
for (const [packageKey, packageRecord] of packageRecordsForIdentity){
|
|
317
327
|
const resolution = requiredYamlRecord(requiredYamlRecord(packageRecord, `pnpm lockfile package ${packageKey}`).resolution, `pnpm lockfile package ${packageKey} resolution`);
|
|
318
328
|
if ('string' != typeof resolution.integrity || !integrityPattern.test(resolution.integrity)) throw new Error(`pnpm lockfile package ${packageKey} has uncertain registry integrity.`);
|
|
319
329
|
if (integrity && integrity !== resolution.integrity) throw new Error(`pnpm lockfile has conflicting registry integrity for ${key}.`);
|
|
320
330
|
integrity = resolution.integrity;
|
|
331
|
+
if (isHttpsTarballLocator(version)) {
|
|
332
|
+
const metadata = requiredYamlRecord(packageRecord, `pnpm lockfile package ${packageKey}`);
|
|
333
|
+
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.`);
|
|
334
|
+
tarballVersion = metadata.version;
|
|
335
|
+
}
|
|
321
336
|
}
|
|
337
|
+
if (void 0 !== tarballVersion) return void tarballs.push({
|
|
338
|
+
packageName,
|
|
339
|
+
version: tarballVersion,
|
|
340
|
+
url: version,
|
|
341
|
+
integrity: integrity,
|
|
342
|
+
path
|
|
343
|
+
});
|
|
322
344
|
return {
|
|
323
345
|
packageName,
|
|
324
346
|
version,
|
|
@@ -333,6 +355,7 @@ function discoverReachablePnpmLockReleaseAgeClosure(lockfile) {
|
|
|
333
355
|
unresolved.sort((left, right)=>JSON.stringify(left).localeCompare(JSON.stringify(right)));
|
|
334
356
|
return {
|
|
335
357
|
candidates,
|
|
358
|
+
tarballs,
|
|
336
359
|
unresolved
|
|
337
360
|
};
|
|
338
361
|
}
|
|
@@ -45,11 +45,16 @@ const external_node_fs_namespaceObject = require("node:fs");
|
|
|
45
45
|
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
|
|
46
46
|
const external_node_path_namespaceObject = require("node:path");
|
|
47
47
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
48
|
+
const utils_namespaceObject = require("@modern-js/utils");
|
|
48
49
|
const policy_cjs_namespaceObject = require("../../../ultramodern-workspace/policy.cjs");
|
|
49
50
|
const { toolchain } = policy_cjs_namespaceObject.ULTRAMODERN_WORKSPACE_POLICY;
|
|
50
51
|
const retiredRootToolingDependencies = [
|
|
51
52
|
"@typescript/typescript6"
|
|
52
53
|
];
|
|
54
|
+
function migrationPnpmVersion(value) {
|
|
55
|
+
const baseline = toolchain.packageManager.version;
|
|
56
|
+
return 'string' == typeof value && utils_namespaceObject.semver.valid(value) && utils_namespaceObject.semver.major(value) === utils_namespaceObject.semver.major(baseline) && utils_namespaceObject.semver.gte(value, baseline) ? value : baseline;
|
|
57
|
+
}
|
|
53
58
|
function isRecord(value) {
|
|
54
59
|
return Boolean(value) && 'object' == typeof value && !Array.isArray(value);
|
|
55
60
|
}
|
|
@@ -67,13 +72,14 @@ function updateUltramodernConfigToolchain(config) {
|
|
|
67
72
|
const workspace = ensureRecord(config, 'workspace', 'workspace');
|
|
68
73
|
const packageManager = ensureRecord(workspace, 'packageManager', 'workspace.packageManager');
|
|
69
74
|
packageManager.name = toolchain.packageManager.name;
|
|
70
|
-
packageManager.version =
|
|
75
|
+
packageManager.version = migrationPnpmVersion(packageManager.version);
|
|
71
76
|
const node = ensureRecord(workspace, 'node', 'workspace.node');
|
|
72
77
|
node.version = toolchain.node.version;
|
|
73
78
|
node.engineRange = toolchain.node.engineRange;
|
|
74
79
|
}
|
|
75
80
|
function updateRootPackageToolchain(packageJson) {
|
|
76
|
-
packageJson.packageManager
|
|
81
|
+
const currentVersion = 'string' == typeof packageJson.packageManager ? packageJson.packageManager.match(/^pnpm@([^+]+)(?:\+.*)?$/u)?.[1] : void 0;
|
|
82
|
+
packageJson.packageManager = `${toolchain.packageManager.name}@${migrationPnpmVersion(currentVersion)}`;
|
|
77
83
|
const engines = ensureRecord(packageJson, 'engines', 'package.json engines');
|
|
78
84
|
engines.node = toolchain.node.engineRange;
|
|
79
85
|
engines.pnpm = toolchain.packageManager.engineRange;
|
|
@@ -83,7 +89,7 @@ function updateRootPackageToolchain(packageJson) {
|
|
|
83
89
|
devDependencies['@types/node'] = policy_cjs_namespaceObject.ULTRAMODERN_PACKAGE_PINS.rootDevDependencies["@types/node"];
|
|
84
90
|
devDependencies.miniflare = policy_cjs_namespaceObject.ULTRAMODERN_PACKAGE_PINS.rootDevDependencies.miniflare;
|
|
85
91
|
}
|
|
86
|
-
function updateMiseTools(content) {
|
|
92
|
+
function updateMiseTools(content, pnpmVersion) {
|
|
87
93
|
const lines = content.replace(/\r\n/gu, '\n').split('\n');
|
|
88
94
|
if ('' === lines.at(-1)) lines.pop();
|
|
89
95
|
let toolsStart = lines.findIndex((line)=>/^\s*\[tools\]\s*(?:#.*)?$/u.test(line));
|
|
@@ -110,13 +116,15 @@ function updateMiseTools(content) {
|
|
|
110
116
|
lines[index] = line;
|
|
111
117
|
};
|
|
112
118
|
upsertTool('node', toolchain.node.version);
|
|
113
|
-
upsertTool('pnpm',
|
|
119
|
+
upsertTool('pnpm', pnpmVersion);
|
|
114
120
|
return `${lines.join('\n')}\n`;
|
|
115
121
|
}
|
|
116
122
|
function updateGeneratedToolchainFiles(io) {
|
|
117
123
|
const misePath = external_node_path_default().join(io.workspaceRoot, '.mise.toml');
|
|
118
124
|
const miseContent = external_node_fs_default().existsSync(misePath) ? external_node_fs_default().readFileSync(misePath, 'utf-8') : '';
|
|
119
|
-
io.
|
|
125
|
+
const packageJson = JSON.parse(external_node_fs_default().readFileSync(external_node_path_default().join(io.workspaceRoot, 'package.json'), 'utf8'));
|
|
126
|
+
const pnpmVersion = migrationPnpmVersion(packageJson.packageManager?.match(/^pnpm@([^+]+)(?:\+.*)?$/u)?.[1]);
|
|
127
|
+
io.write(misePath, updateMiseTools(miseContent, pnpmVersion));
|
|
120
128
|
const workflowPath = external_node_path_default().join(io.workspaceRoot, '.github/workflows/ultramodern-workspace-gates.yml');
|
|
121
129
|
if (!external_node_fs_default().existsSync(workflowPath)) return;
|
|
122
130
|
const workflow = external_node_fs_default().readFileSync(workflowPath, 'utf-8');
|
package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/workspace-artifact-ownership.cjs
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.n = (module)=>{
|
|
5
|
+
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
6
|
+
__webpack_require__.d(getter, {
|
|
7
|
+
a: getter
|
|
8
|
+
});
|
|
9
|
+
return getter;
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
(()=>{
|
|
13
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
14
|
+
var define = (defs, kind)=>{
|
|
15
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
[kind]: defs[key]
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
define(getters, "get");
|
|
21
|
+
define(values, "value");
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
(()=>{
|
|
25
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
26
|
+
})();
|
|
27
|
+
(()=>{
|
|
28
|
+
__webpack_require__.r = (exports1)=>{
|
|
29
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
30
|
+
value: 'Module'
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
33
|
+
value: true
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
37
|
+
var __webpack_exports__ = {};
|
|
38
|
+
__webpack_require__.r(__webpack_exports__);
|
|
39
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
40
|
+
preserveConsumerWorkspaceArtifacts: ()=>preserveConsumerWorkspaceArtifacts
|
|
41
|
+
});
|
|
42
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
43
|
+
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
|
|
44
|
+
const external_node_path_namespaceObject = require("node:path");
|
|
45
|
+
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
46
|
+
const parser_namespaceObject = require("@babel/parser");
|
|
47
|
+
const fs_io_cjs_namespaceObject = require("../../../ultramodern-workspace/fs-io.cjs");
|
|
48
|
+
function isLiteralData(node, literalIdentifiers) {
|
|
49
|
+
if (!node) return false;
|
|
50
|
+
if ('Identifier' === node.type) return literalIdentifiers?.has(node.name) ?? false;
|
|
51
|
+
if ([
|
|
52
|
+
'StringLiteral',
|
|
53
|
+
'NumericLiteral',
|
|
54
|
+
'BooleanLiteral',
|
|
55
|
+
'NullLiteral'
|
|
56
|
+
].includes(node.type)) return true;
|
|
57
|
+
if ('UnaryExpression' === node.type) return '-' === node.operator && 'NumericLiteral' === node.argument.type;
|
|
58
|
+
if ('ArrayExpression' === node.type) return node.elements.every((element)=>isLiteralData(element, literalIdentifiers));
|
|
59
|
+
return 'ObjectExpression' === node.type && node.properties.every((property)=>'ObjectProperty' === property.type && !property.computed && !property.shorthand && [
|
|
60
|
+
'Identifier',
|
|
61
|
+
'StringLiteral',
|
|
62
|
+
'NumericLiteral'
|
|
63
|
+
].includes(property.key.type) && isLiteralData(property.value, literalIdentifiers));
|
|
64
|
+
}
|
|
65
|
+
function withoutGeneratedData(source, binding) {
|
|
66
|
+
if (!binding) return source;
|
|
67
|
+
const parsed = (0, parser_namespaceObject.parse)(source, {
|
|
68
|
+
sourceType: 'module',
|
|
69
|
+
plugins: [
|
|
70
|
+
"typescript"
|
|
71
|
+
]
|
|
72
|
+
});
|
|
73
|
+
for (const statement of parsed.program.body)if ('VariableDeclaration' === statement.type && 'const' === statement.kind) {
|
|
74
|
+
for (const declaration of statement.declarations)if ('Identifier' === declaration.id.type && declaration.id.name === binding && declaration.init && isLiteralData(declaration.init)) return source.slice(0, declaration.init.start) + '{}' + source.slice(declaration.init.end);
|
|
75
|
+
}
|
|
76
|
+
return source;
|
|
77
|
+
}
|
|
78
|
+
function staticPropertyValue(node, name) {
|
|
79
|
+
if (node?.type !== 'ObjectExpression') return;
|
|
80
|
+
const keys = new Set();
|
|
81
|
+
let value;
|
|
82
|
+
for (const property of node.properties){
|
|
83
|
+
if ('ObjectProperty' !== property.type || property.computed || property.shorthand || ![
|
|
84
|
+
'Identifier',
|
|
85
|
+
'StringLiteral'
|
|
86
|
+
].includes(property.key.type)) return;
|
|
87
|
+
const key = property.key.name ?? property.key.value;
|
|
88
|
+
if (keys.has(key)) return;
|
|
89
|
+
keys.add(key);
|
|
90
|
+
if (key === name) value = property.value;
|
|
91
|
+
}
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
function refreshValidatorReleaseCohort(source, releaseCohort) {
|
|
95
|
+
try {
|
|
96
|
+
const parsed = (0, parser_namespaceObject.parse)(source, {
|
|
97
|
+
sourceType: 'module',
|
|
98
|
+
plugins: [
|
|
99
|
+
"typescript"
|
|
100
|
+
],
|
|
101
|
+
tokens: true
|
|
102
|
+
});
|
|
103
|
+
const constants = parsed.program.body.flatMap((statement)=>'VariableDeclaration' === statement.type && 'const' === statement.kind ? statement.declarations : []);
|
|
104
|
+
const matches = [];
|
|
105
|
+
for (const statement of parsed.program.body)if ('VariableDeclaration' === statement.type && 'const' === statement.kind) for (const declaration of statement.declarations){
|
|
106
|
+
const kind = staticPropertyValue(declaration.init, 'kind');
|
|
107
|
+
if (kind?.type !== 'StringLiteral' || 'modernjs.ultramodern-workspace-validation-contract' !== kind.value) continue;
|
|
108
|
+
const cohort = staticPropertyValue(staticPropertyValue(declaration.init, 'cohort'), 'releaseCohort');
|
|
109
|
+
const schema = staticPropertyValue(cohort, 'schema');
|
|
110
|
+
const schemaVersion = staticPropertyValue(cohort, 'schemaVersion');
|
|
111
|
+
const version = staticPropertyValue(staticPropertyValue(cohort, 'release'), 'version');
|
|
112
|
+
const versionConstant = version?.type === 'Identifier' ? constants.find((declaration)=>'Identifier' === declaration.id.type && declaration.id.name === version.name && declaration.init?.type === 'StringLiteral') : void 0;
|
|
113
|
+
if (schema?.type === 'StringLiteral' && 'bleedingdev.ultramodern.release-cohort' === schema.value && schemaVersion?.type === 'NumericLiteral' && 1 === schemaVersion.value && isLiteralData(cohort, versionConstant ? new Set([
|
|
114
|
+
version.name
|
|
115
|
+
]) : void 0)) matches.push({
|
|
116
|
+
cohort,
|
|
117
|
+
version,
|
|
118
|
+
versionConstant
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (1 !== matches.length) return source;
|
|
122
|
+
const { cohort, version, versionConstant } = matches[0];
|
|
123
|
+
let content = JSON.stringify(releaseCohort, null, 2);
|
|
124
|
+
const edits = [];
|
|
125
|
+
if (versionConstant && !parsed.tokens?.some((token)=>'name' === token.type.label && token.value === version.name && token.start !== versionConstant.id.start && (token.start < cohort.start || token.end > cohort.end))) {
|
|
126
|
+
content = content.replaceAll(`"version": ${JSON.stringify(releaseCohort.release.version)}`, `"version": ${version.name}`);
|
|
127
|
+
edits.push({
|
|
128
|
+
start: versionConstant.init.start,
|
|
129
|
+
end: versionConstant.init.end,
|
|
130
|
+
content: JSON.stringify(releaseCohort.release.version)
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
edits.push({
|
|
134
|
+
start: cohort.start,
|
|
135
|
+
end: cohort.end,
|
|
136
|
+
content
|
|
137
|
+
});
|
|
138
|
+
for (const edit of edits.toSorted((left, right)=>right.start - left.start))source = source.slice(0, edit.start) + edit.content + source.slice(edit.end);
|
|
139
|
+
return source;
|
|
140
|
+
} catch {
|
|
141
|
+
return source;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function preserveConsumerWorkspaceArtifacts(io, candidates) {
|
|
145
|
+
const preservedPaths = new Set();
|
|
146
|
+
const physicalRoot = external_node_fs_default().realpathSync(io.workspaceRoot);
|
|
147
|
+
const canonicalSources = (0, fs_io_cjs_namespaceObject.formatGeneratedSourceCandidates)(candidates.map((candidate, index)=>[
|
|
148
|
+
`canonical/${index}/${candidate.relativePath}`,
|
|
149
|
+
withoutGeneratedData(candidate.content, candidate.generatedDataBinding)
|
|
150
|
+
]));
|
|
151
|
+
for (const [index, candidate] of candidates.entries()){
|
|
152
|
+
const paths = [
|
|
153
|
+
candidate.relativePath,
|
|
154
|
+
candidate.legacyPath
|
|
155
|
+
].filter((value)=>void 0 !== value);
|
|
156
|
+
for (const relativePath of paths){
|
|
157
|
+
const filePath = external_node_path_default().join(io.workspaceRoot, relativePath);
|
|
158
|
+
if (!external_node_fs_default().existsSync(filePath)) continue;
|
|
159
|
+
const physicalRelative = external_node_path_default().relative(physicalRoot, external_node_fs_default().realpathSync(filePath));
|
|
160
|
+
if ('..' === physicalRelative || physicalRelative.startsWith(`..${external_node_path_default().sep}`) || external_node_path_default().isAbsolute(physicalRelative)) throw new Error(`Refusing to inspect an artifact outside the workspace: ${relativePath}`);
|
|
161
|
+
const source = external_node_fs_default().readFileSync(filePath, 'utf8');
|
|
162
|
+
let recognized = source === candidate.content;
|
|
163
|
+
if (!recognized) try {
|
|
164
|
+
const normalized = withoutGeneratedData(source, candidate.generatedDataBinding);
|
|
165
|
+
const canonical = canonicalSources[index];
|
|
166
|
+
recognized = normalized === canonical || (0, fs_io_cjs_namespaceObject.formatGeneratedSourceCandidates)([
|
|
167
|
+
[
|
|
168
|
+
relativePath,
|
|
169
|
+
normalized
|
|
170
|
+
]
|
|
171
|
+
])[0] === canonical;
|
|
172
|
+
} catch {}
|
|
173
|
+
if (!recognized) for (const pairedPath of paths)preservedPaths.add(pairedPath);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const reported = new Set();
|
|
177
|
+
const isPreserved = (filePath)=>{
|
|
178
|
+
const relativePath = external_node_path_default().relative(io.workspaceRoot, filePath).split(external_node_path_default().sep).join('/');
|
|
179
|
+
if (!preservedPaths.has(relativePath)) return false;
|
|
180
|
+
if (!reported.has(relativePath)) {
|
|
181
|
+
io.log(`${relativePath} preserved consumer-owned artifact: its canonical generated source does not match.`);
|
|
182
|
+
reported.add(relativePath);
|
|
183
|
+
}
|
|
184
|
+
return true;
|
|
185
|
+
};
|
|
186
|
+
return {
|
|
187
|
+
preservedPaths,
|
|
188
|
+
refreshReleaseCohort (releaseCohort) {
|
|
189
|
+
if (!releaseCohort) return;
|
|
190
|
+
for (const candidate of candidates)if ('workspaceValidationContract' === candidate.generatedDataBinding) for (const relativePath of [
|
|
191
|
+
candidate.relativePath,
|
|
192
|
+
candidate.legacyPath
|
|
193
|
+
]){
|
|
194
|
+
if (!relativePath || !preservedPaths.has(relativePath)) continue;
|
|
195
|
+
const filePath = external_node_path_default().join(io.workspaceRoot, relativePath);
|
|
196
|
+
if (!external_node_fs_default().existsSync(filePath)) continue;
|
|
197
|
+
const source = external_node_fs_default().readFileSync(filePath, 'utf8');
|
|
198
|
+
io.write(filePath, refreshValidatorReleaseCohort(source, releaseCohort));
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
io: {
|
|
202
|
+
...io,
|
|
203
|
+
write: (filePath, content)=>isPreserved(filePath) ? false : io.write(filePath, content),
|
|
204
|
+
writeGenerated: (filePath, content)=>isPreserved(filePath) ? false : io.writeGenerated(filePath, content),
|
|
205
|
+
remove: (filePath)=>isPreserved(filePath) ? false : io.remove(filePath)
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
exports.preserveConsumerWorkspaceArtifacts = __webpack_exports__.preserveConsumerWorkspaceArtifacts;
|
|
210
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
211
|
+
"preserveConsumerWorkspaceArtifacts"
|
|
212
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
213
|
+
Object.defineProperty(exports, '__esModule', {
|
|
214
|
+
value: true
|
|
215
|
+
});
|