diff --git a/packages/pnpm/src/cmd/link.ts b/packages/pnpm/src/cmd/link.ts index b1f3ceeff9..691e9cda16 100644 --- a/packages/pnpm/src/cmd/link.ts +++ b/packages/pnpm/src/cmd/link.ts @@ -8,9 +8,10 @@ import { InstallOptions, link, linkToGlobal, + LocalPackages, } from 'supi' import { cached as createStoreController } from '../createStoreController' -import findWorkspacePackages from '../findWorkspacePackages' +import findWorkspacePackages, { arrayOfLocalPackagesToMap } from '../findWorkspacePackages' import getConfigs from '../getConfigs' import { PnpmOptions } from '../types' @@ -23,9 +24,18 @@ export default async ( const cwd = opts && opts.prefix || process.cwd() const storeControllerCache = new Map>() + let workspacePackages + let localPackages!: LocalPackages + if (opts.linkWorkspacePackages && opts.workspacePrefix) { + workspacePackages = await findWorkspacePackages(opts.workspacePrefix) + localPackages = arrayOfLocalPackagesToMap(workspacePackages) + } else { + localPackages = {} + } const store = await createStoreController(storeControllerCache, opts) const linkOpts = Object.assign(opts, { + localPackages, store: store.path, storeController: store.ctrl, }) @@ -41,9 +51,9 @@ export default async ( if (pkgNames.length) { let globalPkgNames!: string[] if (opts.workspacePrefix) { - const pkgs = await findWorkspacePackages(opts.workspacePrefix) + workspacePackages = await findWorkspacePackages(opts.workspacePrefix) - const pkgsFoundInWorkspace = pkgs.filter((pkg) => pkgNames.indexOf(pkg.manifest.name) !== -1) + const pkgsFoundInWorkspace = workspacePackages.filter((pkg) => pkgNames.indexOf(pkg.manifest.name) !== -1) pkgsFoundInWorkspace.forEach((pkgFromWorkspace) => pkgPaths.push(pkgFromWorkspace.path)) if (pkgsFoundInWorkspace.length && !linkOpts.saveDev && !linkOpts.saveProd && !linkOpts.saveOptional) { @@ -63,6 +73,7 @@ export default async ( const s = await createStoreController(storeControllerCache, opts) await install({ ...await getConfigs({ ...opts.cliArgs, prefix }, { excludeReporter: true }), + localPackages, store: s.path, storeController: s.ctrl, } as InstallOptions) diff --git a/packages/pnpm/test/monorepo/index.ts b/packages/pnpm/test/monorepo/index.ts index bf9e45dcec..5071ff4586 100644 --- a/packages/pnpm/test/monorepo/index.ts +++ b/packages/pnpm/test/monorepo/index.ts @@ -459,3 +459,30 @@ test('recursive installation with shared-workspace-shrinkwrap and a readPackage await projects['project-1'].hasNot('project-1') }) + +test('local packages should be preferred when running "pnpm link" inside a workspace', async (t) => { + const projects = preparePackages(t, [ + { + name: 'project-1', + version: '1.0.0', + dependencies: { + 'is-positive': '1.0.0', + }, + }, + { + name: 'is-positive', + version: '1.0.0', + }, + ]) + + await writeYamlFile('pnpm-workspace.yaml', { packages: ['**', '!store/**'] }) + await fs.writeFile('.npmrc', 'link-workspace-packages = true', 'utf8') + + process.chdir('project-1') + + await execPnpm('link', '.') + + const shr = await projects['project-1'].loadShrinkwrap() + + t.equal(shr && shr.dependencies && shr.dependencies['is-positive'], 'link:../is-positive') +}) diff --git a/packages/supi/src/index.ts b/packages/supi/src/index.ts index 8c4c9761ae..4fd6efc5bb 100644 --- a/packages/supi/src/index.ts +++ b/packages/supi/src/index.ts @@ -41,6 +41,8 @@ export { UninstallOptions } from './uninstall/extendUninstallOptions' import * as packageRequesterLogs from '@pnpm/package-requester' import * as supiLogs from './loggers' +export { LocalPackages } from '@pnpm/resolver-base' + export type ProgressLog = ProgressLog | packageRequesterLogs.ProgressLog export type Log = supiLogs.Log | packageRequesterLogs.Log