Override core resolvers with plugin #6658
-
I have a use case where I want to control the way that a particular package is resolved. I'd imagined that I could do something like this: class CustomResolver extends NpmSemverResolver {
async resolve(locator: Locator, opts: ResolveOptions) {
if (isSpecialLocator(locator)) {
return getSpecialPackageDefinition(locator);
}
// Fall back to the default npm resolver for other cases
return super.resolve(locator, opts);
}
}
module.exports = {
name: `plugin-custom-resolve`,
factory: () => {
return {
resolvers: [CustomResolver],
};
},
} satisfies Plugin; To my surprise, though, the custom resolver never gets called for normal-looking dependencies. I was only able to get Yarn to call it by adding a dependency in my "dependencies": {
"my-dep": "weird-version-specifier"
} Based on this code, it looks like resolvers and linkers from plugins will always be called after the core resolvers. That seems like a major limitation for plugins. Is that right, or is there something I'm missing? Related discussion: #2702 The suggestion there was "You can also write a resolver plugin that handles this one particular package," but I don't understand how that would work for the use case proposed there: If the package looks like something that |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
It turns out that it's already possible to "override" the core resolvers. The trick is to alter the protocol of the dependencies you want to resolve yourself using the class CustomResolver implements Resolver {
supportsDescriptor(descriptor: Descriptor, opts: MinimalResolveOptions) {
return descriptor.range.startsWith(CUSTOM_PROTOCOL);
}
// other methods...
}
module.exports = {
name: `plugin-custom-resolve`,
factory: (): Plugin => {
return {
resolvers: [CustomResolver],
hooks: {
reduceDependency: async (dependency: Descriptor) => {
if (shouldUseCustomResolver(dependency)) {
const range = structUtils.parseRange(dependency.range);
return structUtils.makeDescriptor(
dependency,
structUtils.makeRange({
...range,
protocol: CUSTOM_PROTOCOL,
})
);
}
return dependency;
},
},
};
},
}; Thanks to @clemyan for helping me figure this out! |
Beta Was this translation helpful? Give feedback.
It turns out that it's already possible to "override" the core resolvers. The trick is to alter the protocol of the dependencies you want to resolve yourself using the
reduceDependency
hook. Since none of the core resolvers recognize that protocol, your custom resolver will get to handle those dependencies: