Skip to content

Commit 1064419

Browse files
committed
drop protocol after normalization
1 parent a592371 commit 1064419

File tree

1 file changed

+43
-8
lines changed

1 file changed

+43
-8
lines changed

packages/plugin-catalog/sources/index.ts

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,44 @@
1-
import {type Descriptor, type Locator, type Plugin, type Project, type Resolver, type ResolveOptions, type Workspace, SettingsType, structUtils, Manifest, ThrowReport} from '@yarnpkg/core';
2-
import {Hooks as CoreHooks} from '@yarnpkg/core';
3-
import {Hooks as PackHooks} from '@yarnpkg/plugin-pack';
1+
import {type Descriptor, type Locator, type Plugin, type Project, type Resolver, type ResolveOptions, type Workspace, SettingsType, structUtils, Manifest, ThrowReport, Configuration} from '@yarnpkg/core';
2+
import {Hooks as CoreHooks} from '@yarnpkg/core';
3+
import {Hooks as PackHooks} from '@yarnpkg/plugin-pack';
44

5-
import {isCatalogReference, resolveDescriptorFromCatalog} from './utils';
5+
import {isCatalogReference, resolveDescriptorFromCatalog} from './utils';
6+
7+
const SAFE_PROTOCOLS_TO_ALWAYS_KEEP = new Set<string>([`patch:`, `portal:`, `link:`]);
8+
9+
function tryRoundTripRange(range: string, configuration: Configuration): string {
10+
try {
11+
const parsed = structUtils.parseRange(range);
12+
let {protocol, source, params, selector} = parsed;
13+
14+
const defaultProtocol = configuration.get(`defaultProtocol`);
15+
16+
// only drop protocol when it's exactly the default npm protocol and no special semantics needed
17+
const canDropProtocol =
18+
protocol != null &&
19+
protocol === defaultProtocol &&
20+
protocol === `npm:` && // be explicit
21+
!SAFE_PROTOCOLS_TO_ALWAYS_KEEP.has(protocol);
22+
23+
if (canDropProtocol)
24+
protocol = null;
25+
26+
// Replace the catalog reference with the resolved range
27+
const normalized = structUtils.makeRange({protocol, source, params, selector});
28+
29+
// idempotency check: if normalization changes meaningfully, keep original
30+
const reparsed = structUtils.parseRange(normalized);
31+
const sameShape =
32+
reparsed.protocol === (canDropProtocol ? null : parsed.protocol) &&
33+
reparsed.source === parsed.source &&
34+
JSON.stringify(reparsed.params) === JSON.stringify(parsed.params) &&
35+
reparsed.selector === parsed.selector;
36+
37+
return sameShape ? normalized : range;
38+
} catch {
39+
return range;
40+
}
41+
}
642

743
declare module '@yarnpkg/core' {
844
interface ConfigurationValueMap {
@@ -85,12 +121,11 @@ const plugin: Plugin<CoreHooks & PackHooks> = {
85121
// Resolve the catalog reference to get the actual version range
86122
const resolvedDescriptor = resolveDescriptorFromCatalog(project, descriptor, resolver, resolveOptions);
87123

88-
let {protocol, source, params, selector} = structUtils.parseRange(structUtils.convertToManifestRange(resolvedDescriptor.range));
89-
if (protocol === workspace.project.configuration.get(`defaultProtocol`))
90-
protocol = null;
124+
// Convert to manifest range to strip internal params
125+
const resolvedRange = structUtils.convertToManifestRange(resolvedDescriptor.range);
91126

92127
// Replace the catalog reference with the resolved range
93-
dependencies[identStr] = structUtils.makeRange({protocol, source, params, selector});
128+
dependencies[identStr] = tryRoundTripRange(resolvedRange, workspace.project.configuration);
94129
}
95130
}
96131
},

0 commit comments

Comments
 (0)