diff --git a/packages/berry-core/sources/Configuration.ts b/packages/berry-core/sources/Configuration.ts index 50aecac1a4c9..443743ba1fd3 100644 --- a/packages/berry-core/sources/Configuration.ts +++ b/packages/berry-core/sources/Configuration.ts @@ -466,7 +466,7 @@ export class Configuration { * one listed on /foo/bar/.yarnrc, but not the other way around). */ - static async find(startingCwd: PortablePath, pluginConfiguration: PluginConfiguration | null, {strict = true}: {strict?: boolean} = {}) { + static async find(startingCwd: PortablePath, pluginConfiguration: PluginConfiguration | null, {strict = true, useRc = true}: {strict?: boolean, useRc?: boolean} = {}) { const environmentSettings = getEnvironmentSettings(); delete environmentSettings.rcFilename; @@ -486,6 +486,8 @@ export class Configuration { const dynamicPlugins = new Set(); for (const {path, cwd, data} of rcFiles) { + if (!useRc) + continue; if (!Array.isArray(data.plugins)) continue; diff --git a/packages/berry-core/sources/execUtils.ts b/packages/berry-core/sources/execUtils.ts index 63b1a39e9841..e560a8b1d848 100644 --- a/packages/berry-core/sources/execUtils.ts +++ b/packages/berry-core/sources/execUtils.ts @@ -56,7 +56,7 @@ export type ExecvpOptions = { strict?: boolean, }; -export async function execvp(fileName: string, args: Array, opts: ExecvpOptions & {encoding: `buffer`}): Promise<{code: number, stdout: Buffer, stderr: Buffer}>; +export async function execvp(fileName: string, args: Array, opts: ExecvpOptions & {encoding: 'buffer'}): Promise<{code: number, stdout: Buffer, stderr: Buffer}>; export async function execvp(fileName: string, args: Array, opts: ExecvpOptions & {encoding: string}): Promise<{code: number, stdout: string, stderr: string}>; export async function execvp(fileName: string, args: Array, opts: ExecvpOptions): Promise<{code: number, stdout: string, stderr: string}>; diff --git a/packages/plugin-npm/sources/NpmFetcher.ts b/packages/plugin-npm/sources/NpmFetcher.ts index 37a9ec7bde08..d0f57b6866eb 100644 --- a/packages/plugin-npm/sources/NpmFetcher.ts +++ b/packages/plugin-npm/sources/NpmFetcher.ts @@ -51,7 +51,7 @@ export class NpmFetcher implements Fetcher { }); } catch (error) { // The npm registry doesn't always support %2f when fetching the package tarballs 🤡 - // Ex: https://registry.yarnpkg.com/@emotion%2fbabel-preset-css-prop/-/babel-preset-css-prop-10.0.7.tgz0 + // Ex: https://registry.yarnpkg.com/@emotion%2fbabel-preset-css-prop/-/babel-preset-css-prop-10.0.7.tgz sourceBuffer = await npmHttpUtils.get(this.getLocatorUrl(locator, opts).replace(/%2f/g, `/`), { configuration: opts.project.configuration, ident: locator, diff --git a/packages/plugin-npm/sources/npmHttpUtils.ts b/packages/plugin-npm/sources/npmHttpUtils.ts index e86b0aafdd9d..c3dfe75dfec6 100644 --- a/packages/plugin-npm/sources/npmHttpUtils.ts +++ b/packages/plugin-npm/sources/npmHttpUtils.ts @@ -1,7 +1,6 @@ import {Configuration, Ident, httpUtils} from '@berry/core'; import {MessageName, ReportError} from '@berry/core'; import inquirer from 'inquirer'; -import {resolve as resolveUrl} from 'url'; import * as npmConfigUtils from './npmConfigUtils'; import {MapLike} from './npmConfigUtils'; @@ -76,6 +75,10 @@ export async function put(path: string, body: httpUtils.Body, {configuration, he } } +function resolveUrl(registry: string, path: string) { + return registry.replace(/\/+$/, ``) + path; +} + function getAuthenticationHeader(registry: string, {authType = AuthType.CONFIGURATION, configuration}: {authType?: AuthType, configuration: Configuration}) { const registryConfiguration = npmConfigUtils.getRegistryConfiguration(registry, {configuration}); const effectiveConfiguration = registryConfiguration || configuration; diff --git a/packages/plugin-npm/tests/npmHttpUtils.test.js b/packages/plugin-npm/tests/npmHttpUtils.test.js new file mode 100644 index 000000000000..c38e5871c789 --- /dev/null +++ b/packages/plugin-npm/tests/npmHttpUtils.test.js @@ -0,0 +1,43 @@ +import {Configuration, httpUtils} from '@berry/core'; +import {get} from '@berry/plugin-npm/sources/npmHttpUtils'; + +jest.mock(`@berry/core`, () => ({ + ... require.requireActual(`@berry/core`), + httpUtils: { + ... require.requireActual(`@berry/core`).httpUtils, + get: jest.fn(() => Promise.resolve()), + }, +})); + +const makeConfiguration = () => Configuration.find(__dirname, { + modules: new Map([ + [`@berry/core`, require(`@berry/core`)], + [`@berry/fslib`, require(`@berry/core`)], + [`@berry/plugin-npm`, require(`@berry/plugin-npm`)], + ]), + plugins: new Set([ + `@berry/plugin-npm`, + ]), +}, { + useRc: false, + strict: false, +}); + +describe(`npmHttpUtils.get`, () => { + for (const registry of [`https://example.org`, `https://example.org/`, `https://example.org/foo`, `https://example.org/foo/`]) { + for (const path of [`/bar`]) { + const expected = registry.replace(/\/+$/, ``) + path; + + it(`should craft the final path correctly (${registry} + ${path} = ${expected})`, async () => { + const configuration = await makeConfiguration(); + + await get(path, { + configuration, + registry, + }); + + expect(httpUtils.get).toHaveBeenCalledWith(expected, expect.anything()); + }); + } + } +});