mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-24 23:58:07 -05:00
refactor!: pass always all projects to mutateModules() (#5338)
This commit is contained in:
5
.changeset/curvy-panthers-arrive.md
Normal file
5
.changeset/curvy-panthers-arrive.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/get-context": major
|
||||
---
|
||||
|
||||
Breaking changes to the API.
|
||||
5
.changeset/five-socks-push.md
Normal file
5
.changeset/five-socks-push.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/config": minor
|
||||
---
|
||||
|
||||
New field returned: allProjectsGraph.
|
||||
5
.changeset/loud-apples-applaud.md
Normal file
5
.changeset/loud-apples-applaud.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-installation": major
|
||||
---
|
||||
|
||||
New required option added: `allProjectsGraph`.
|
||||
6
.changeset/thick-ties-leave.md
Normal file
6
.changeset/thick-ties-leave.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/core": major
|
||||
"@pnpm/headless": major
|
||||
---
|
||||
|
||||
Breaking changes to the API. All projects must be passed via a new field in options.
|
||||
5
.changeset/violet-impalas-brush.md
Normal file
5
.changeset/violet-impalas-brush.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/filter-workspace-packages": minor
|
||||
---
|
||||
|
||||
`readProjects()` returns `allProjectsGraph`.
|
||||
@@ -11,6 +11,7 @@ export type UniversalOptions = Pick<Config, 'color' | 'dir' | 'rawConfig' | 'raw
|
||||
export interface Config {
|
||||
allProjects?: Project[]
|
||||
selectedProjectsGraph?: ProjectsGraph
|
||||
allProjectsGraph?: ProjectsGraph
|
||||
|
||||
allowNew: boolean
|
||||
autoInstallPeers?: boolean
|
||||
|
||||
@@ -27,7 +27,7 @@ export async function getPeerDependencyIssues (
|
||||
opts: ListMissingPeersOptions
|
||||
): Promise<PeerDependencyIssuesByProjects> {
|
||||
const lockfileDir = opts.lockfileDir ?? process.cwd()
|
||||
const ctx = await getContext(projects, {
|
||||
const ctx = await getContext({
|
||||
force: false,
|
||||
forceSharedLockfile: false,
|
||||
extraBinPaths: [],
|
||||
@@ -35,9 +35,10 @@ export async function getPeerDependencyIssues (
|
||||
nodeLinker: opts.nodeLinker ?? 'isolated',
|
||||
registries: DEFAULT_REGISTRIES,
|
||||
useLockfile: true,
|
||||
allProjects: projects,
|
||||
...opts,
|
||||
})
|
||||
const projectsToResolve = ctx.projects.map((project) => ({
|
||||
const projectsToResolve = Object.values(ctx.projects).map((project) => ({
|
||||
...project,
|
||||
updatePackageManifest: false,
|
||||
wantedDependencies: getWantedDependencies(project.manifest),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { WANTED_LOCKFILE } from '@pnpm/constants'
|
||||
import PnpmError from '@pnpm/error'
|
||||
import { ProjectOptions } from '@pnpm/get-context'
|
||||
import { HoistingLimits } from '@pnpm/headless'
|
||||
import { createReadPackageHook } from '@pnpm/hooks.read-package-hook'
|
||||
import { Lockfile } from '@pnpm/lockfile-file'
|
||||
@@ -113,6 +114,8 @@ export interface StrictInstallOptions {
|
||||
global: boolean
|
||||
globalBin?: string
|
||||
patchedDependencies?: Record<string, string>
|
||||
|
||||
allProjects: ProjectOptions[]
|
||||
}
|
||||
|
||||
export type InstallOptions =
|
||||
|
||||
@@ -12,8 +12,8 @@ import {
|
||||
} from '@pnpm/core-loggers'
|
||||
import { createBase32HashFromFile } from '@pnpm/crypto.base32-hash'
|
||||
import PnpmError from '@pnpm/error'
|
||||
import getContext, { PnpmContext, ProjectOptions } from '@pnpm/get-context'
|
||||
import headless, { Project } from '@pnpm/headless'
|
||||
import getContext, { PnpmContext } from '@pnpm/get-context'
|
||||
import headless from '@pnpm/headless'
|
||||
import runLifecycleHook, {
|
||||
makeNodeRequireOption,
|
||||
runLifecycleHooksConcurrently,
|
||||
@@ -85,7 +85,6 @@ const DEV_PREINSTALL = 'pnpm:devPreinstall'
|
||||
|
||||
export type DependenciesMutation = (
|
||||
{
|
||||
buildIndex: number
|
||||
mutation: 'install'
|
||||
pruneDirectDependencies?: boolean
|
||||
} | {
|
||||
@@ -106,30 +105,32 @@ export type DependenciesMutation = (
|
||||
mutation: 'unlinkSome'
|
||||
dependencyNames: string[]
|
||||
}
|
||||
) & (
|
||||
{
|
||||
manifest: ProjectManifest
|
||||
}
|
||||
)
|
||||
|
||||
export async function install (
|
||||
manifest: ProjectManifest,
|
||||
opts: InstallOptions & {
|
||||
opts: Omit<InstallOptions, 'allProjects'> & {
|
||||
preferredVersions?: PreferredVersions
|
||||
pruneDirectDependencies?: boolean
|
||||
}
|
||||
) {
|
||||
const rootDir = opts.dir ?? process.cwd()
|
||||
const projects = await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
pruneDirectDependencies: opts.pruneDirectDependencies,
|
||||
rootDir: opts.dir ?? process.cwd(),
|
||||
rootDir,
|
||||
},
|
||||
],
|
||||
opts
|
||||
{
|
||||
...opts,
|
||||
allProjects: [{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
rootDir,
|
||||
}],
|
||||
}
|
||||
)
|
||||
return projects[0].manifest
|
||||
}
|
||||
@@ -142,7 +143,7 @@ interface ProjectToBeInstalled {
|
||||
rootDir: string
|
||||
}
|
||||
|
||||
export type MutatedProject = ProjectOptions & DependenciesMutation
|
||||
export type MutatedProject = DependenciesMutation & { rootDir: string }
|
||||
|
||||
export type MutateModulesOptions = InstallOptions & {
|
||||
preferredVersions?: PreferredVersions
|
||||
@@ -151,6 +152,28 @@ export type MutateModulesOptions = InstallOptions & {
|
||||
} | InstallOptions['hooks']
|
||||
}
|
||||
|
||||
export async function mutateModulesInSingleProject (
|
||||
project: MutatedProject & {
|
||||
binsDir?: string
|
||||
manifest: ProjectManifest
|
||||
rootDir: string
|
||||
modulesDir?: string
|
||||
},
|
||||
maybeOpts: Omit<MutateModulesOptions, 'allProjects'>
|
||||
): Promise<UpdatedProject> {
|
||||
const [updatedProject] = await mutateModules(
|
||||
[project],
|
||||
{
|
||||
...maybeOpts,
|
||||
allProjects: [{
|
||||
buildIndex: 0,
|
||||
...project,
|
||||
}],
|
||||
}
|
||||
)
|
||||
return updatedProject
|
||||
}
|
||||
|
||||
export async function mutateModules (
|
||||
projects: MutatedProject[],
|
||||
maybeOpts: MutateModulesOptions
|
||||
@@ -169,12 +192,12 @@ export async function mutateModules (
|
||||
const installsOnly = projects.every((project) => project.mutation === 'install')
|
||||
if (!installsOnly) opts.strictPeerDependencies = false
|
||||
opts['forceNewModules'] = installsOnly
|
||||
const rootProjectManifest = projects.find(({ rootDir }) => rootDir === opts.lockfileDir)?.manifest ??
|
||||
const rootProjectManifest = opts.allProjects.find(({ rootDir }) => rootDir === opts.lockfileDir)?.manifest ??
|
||||
// When running install/update on a subset of projects, the root project might not be included,
|
||||
// so reading its manifest explicitly here.
|
||||
await safeReadProjectManifestOnly(opts.lockfileDir)
|
||||
|
||||
const ctx = await getContext(projects, opts)
|
||||
const ctx = await getContext(opts)
|
||||
|
||||
if (opts.hooks.preResolution) {
|
||||
await opts.hooks.preResolution({
|
||||
@@ -192,7 +215,7 @@ export async function mutateModules (
|
||||
: true
|
||||
|
||||
if (!maybeOpts.ignorePackageManifest) {
|
||||
for (const { manifest, rootDir } of ctx.projects) {
|
||||
for (const { manifest, rootDir } of Object.values(ctx.projects)) {
|
||||
if (!manifest) {
|
||||
throw new Error(`No package.json found in "${rootDir}"`)
|
||||
}
|
||||
@@ -277,10 +300,10 @@ export async function mutateModules (
|
||||
opts.ignorePackageManifest ||
|
||||
!needsFullResolution &&
|
||||
opts.preferFrozenLockfile &&
|
||||
(!opts.pruneLockfileImporters || Object.keys(ctx.wantedLockfile.importers).length === ctx.projects.length) &&
|
||||
(!opts.pruneLockfileImporters || Object.keys(ctx.wantedLockfile.importers).length === Object.keys(ctx.projects).length) &&
|
||||
ctx.existsWantedLockfile &&
|
||||
ctx.wantedLockfile.lockfileVersion === LOCKFILE_VERSION &&
|
||||
await allProjectsAreUpToDate(ctx.projects, {
|
||||
await allProjectsAreUpToDate(Object.values(ctx.projects), {
|
||||
autoInstallPeers: opts.autoInstallPeers,
|
||||
linkWorkspacePackages: opts.linkWorkspacePackagesDepth >= 0,
|
||||
wantedLockfile: ctx.wantedLockfile,
|
||||
@@ -294,10 +317,10 @@ export async function mutateModules (
|
||||
})
|
||||
}
|
||||
if (opts.lockfileOnly) {
|
||||
return projects
|
||||
return projects.map((mutatedProject) => ctx.projects[mutatedProject.rootDir])
|
||||
}
|
||||
if (!ctx.existsWantedLockfile) {
|
||||
if (ctx.projects.some((project) => pkgHasDependencies(project.manifest))) {
|
||||
if (Object.values(ctx.projects).some((project) => pkgHasDependencies(project.manifest))) {
|
||||
throw new Error(`Headless installation requires a ${WANTED_LOCKFILE} file`)
|
||||
}
|
||||
} else {
|
||||
@@ -315,7 +338,8 @@ export async function mutateModules (
|
||||
pnpmVersion: opts.packageManager.name === 'pnpm' ? opts.packageManager.version : '',
|
||||
},
|
||||
patchedDependencies: patchedDependenciesWithResolvedPath,
|
||||
projects: ctx.projects as Project[],
|
||||
selectedProjectDirs: projects.map((project) => project.rootDir),
|
||||
allProjects: ctx.projects,
|
||||
prunedAt: ctx.modulesFile?.prunedAt,
|
||||
pruneVirtualStore,
|
||||
wantedLockfile: maybeOpts.ignorePackageManifest ? undefined : ctx.wantedLockfile,
|
||||
@@ -332,7 +356,13 @@ export async function mutateModules (
|
||||
mergeGitBranchLockfiles: opts.mergeGitBranchLockfiles,
|
||||
})
|
||||
}
|
||||
return projects
|
||||
return projects.map((mutatedProject) => {
|
||||
const project = ctx.projects[mutatedProject.rootDir]
|
||||
return {
|
||||
...project,
|
||||
manifest: project.originalManifest ?? project.manifest,
|
||||
}
|
||||
})
|
||||
} catch (error: any) { // eslint-disable-line
|
||||
if (
|
||||
frozenLockfile ||
|
||||
@@ -359,12 +389,16 @@ export async function mutateModules (
|
||||
let preferredSpecs: Record<string, string> | null = null
|
||||
|
||||
// TODO: make it concurrent
|
||||
for (const project of ctx.projects) {
|
||||
for (const project of projects) {
|
||||
const projectOpts = {
|
||||
...project,
|
||||
...ctx.projects[project.rootDir],
|
||||
}
|
||||
switch (project.mutation) {
|
||||
case 'uninstallSome':
|
||||
projectsToInstall.push({
|
||||
pruneDirectDependencies: false,
|
||||
...project,
|
||||
...projectOpts,
|
||||
removePackages: project.dependencyNames,
|
||||
updatePackageManifest: true,
|
||||
wantedDependencies: [],
|
||||
@@ -372,48 +406,50 @@ export async function mutateModules (
|
||||
break
|
||||
case 'install': {
|
||||
await installCase({
|
||||
...project,
|
||||
...projectOpts,
|
||||
updatePackageManifest: opts.updatePackageManifest ?? opts.update,
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'installSome': {
|
||||
await installSome({
|
||||
...project,
|
||||
...projectOpts,
|
||||
updatePackageManifest: opts.updatePackageManifest !== false,
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'unlink': {
|
||||
const packageDirs = await readModulesDirs(project.modulesDir)
|
||||
const packageDirs = await readModulesDirs(projectOpts.modulesDir)
|
||||
const externalPackages = await pFilter(
|
||||
packageDirs!,
|
||||
async (packageDir: string) => isExternalLink(ctx.storeDir, project.modulesDir, packageDir)
|
||||
async (packageDir: string) => isExternalLink(ctx.storeDir, projectOpts.modulesDir, packageDir)
|
||||
)
|
||||
const allDeps = getAllDependenciesFromManifest(project.manifest)
|
||||
const allDeps = getAllDependenciesFromManifest(projectOpts.manifest)
|
||||
const packagesToInstall: string[] = []
|
||||
for (const pkgName of externalPackages) {
|
||||
await rimraf(path.join(project.modulesDir, pkgName))
|
||||
await rimraf(path.join(projectOpts.modulesDir, pkgName))
|
||||
if (allDeps[pkgName]) {
|
||||
packagesToInstall.push(pkgName)
|
||||
}
|
||||
}
|
||||
if (packagesToInstall.length === 0) return projects
|
||||
if (packagesToInstall.length === 0) {
|
||||
return projects.map((mutatedProject) => ctx.projects[mutatedProject.rootDir])
|
||||
}
|
||||
|
||||
// TODO: install only those that were unlinked
|
||||
// but don't update their version specs in package.json
|
||||
await installCase({ ...project, mutation: 'install' })
|
||||
await installCase({ ...projectOpts, mutation: 'install' })
|
||||
break
|
||||
}
|
||||
case 'unlinkSome': {
|
||||
if (project.manifest?.name && opts.globalBin) {
|
||||
await removeBin(path.join(opts.globalBin, project.manifest?.name))
|
||||
if (projectOpts.manifest?.name && opts.globalBin) {
|
||||
await removeBin(path.join(opts.globalBin, projectOpts.manifest?.name))
|
||||
}
|
||||
const packagesToInstall: string[] = []
|
||||
const allDeps = getAllDependenciesFromManifest(project.manifest)
|
||||
const allDeps = getAllDependenciesFromManifest(projectOpts.manifest)
|
||||
for (const depName of project.dependencyNames) {
|
||||
try {
|
||||
if (!await isExternalLink(ctx.storeDir, project.modulesDir, depName)) {
|
||||
if (!await isExternalLink(ctx.storeDir, projectOpts.modulesDir, depName)) {
|
||||
logger.warn({
|
||||
message: `${depName} is not an external link`,
|
||||
prefix: project.rootDir,
|
||||
@@ -423,17 +459,19 @@ export async function mutateModules (
|
||||
} catch (err: any) { // eslint-disable-line
|
||||
if (err['code'] !== 'ENOENT') throw err
|
||||
}
|
||||
await rimraf(path.join(project.modulesDir, depName))
|
||||
await rimraf(path.join(projectOpts.modulesDir, depName))
|
||||
if (allDeps[depName]) {
|
||||
packagesToInstall.push(depName)
|
||||
}
|
||||
}
|
||||
if (packagesToInstall.length === 0) return projects
|
||||
if (packagesToInstall.length === 0) {
|
||||
return projects.map((mutatedProject) => ctx.projects[mutatedProject.rootDir])
|
||||
}
|
||||
|
||||
// TODO: install only those that were unlinked
|
||||
// but don't update their version specs in package.json
|
||||
await installSome({
|
||||
...project,
|
||||
...projectOpts,
|
||||
dependencySelectors: packagesToInstall,
|
||||
mutation: 'installSome',
|
||||
updatePackageManifest: false,
|
||||
@@ -599,7 +637,7 @@ function forgetResolutionsOfPrevWantedDeps (importer: ProjectSnapshot, wantedDep
|
||||
export async function addDependenciesToPackage (
|
||||
manifest: ProjectManifest,
|
||||
dependencySelectors: string[],
|
||||
opts: InstallOptions & {
|
||||
opts: Omit<InstallOptions, 'allProjects'> & {
|
||||
bin?: string
|
||||
allowNew?: boolean
|
||||
peer?: boolean
|
||||
@@ -607,28 +645,36 @@ export async function addDependenciesToPackage (
|
||||
targetDependenciesField?: DependenciesField
|
||||
}
|
||||
) {
|
||||
const rootDir = opts.dir ?? process.cwd()
|
||||
const projects = await mutateModules(
|
||||
[
|
||||
{
|
||||
binsDir: opts.bin,
|
||||
allowNew: opts.allowNew,
|
||||
dependencySelectors,
|
||||
manifest,
|
||||
mutation: 'installSome',
|
||||
peer: opts.peer,
|
||||
pinnedVersion: opts.pinnedVersion,
|
||||
rootDir: opts.dir ?? process.cwd(),
|
||||
rootDir,
|
||||
targetDependenciesField: opts.targetDependenciesField,
|
||||
},
|
||||
],
|
||||
{
|
||||
...opts,
|
||||
lockfileDir: opts.lockfileDir ?? opts.dir,
|
||||
allProjects: [
|
||||
{
|
||||
buildIndex: 0,
|
||||
binsDir: opts.bin,
|
||||
manifest,
|
||||
rootDir,
|
||||
},
|
||||
],
|
||||
})
|
||||
return projects[0].manifest
|
||||
}
|
||||
|
||||
export type ImporterToUpdate = {
|
||||
buildIndex: number
|
||||
binsDir: string
|
||||
id: string
|
||||
manifest: ProjectManifest
|
||||
@@ -654,7 +700,7 @@ interface InstallFunctionResult {
|
||||
|
||||
type InstallFunction = (
|
||||
projects: ImporterToUpdate[],
|
||||
ctx: PnpmContext<DependenciesMutation>,
|
||||
ctx: PnpmContext,
|
||||
opts: Omit<StrictInstallOptions, 'patchedDependencies'> & {
|
||||
patchedDependencies?: Record<string, PatchFile>
|
||||
makePartialCurrentLockfile: boolean
|
||||
@@ -1133,7 +1179,8 @@ const installInContext: InstallFunction = async (projects, ctx, opts) => {
|
||||
nodeVersion: opts.nodeVersion,
|
||||
pnpmVersion: opts.packageManager.name === 'pnpm' ? opts.packageManager.version : '',
|
||||
},
|
||||
projects: ctx.projects as Project[],
|
||||
selectedProjectDirs: projects.map((project) => project.rootDir),
|
||||
allProjects: ctx.projects,
|
||||
prunedAt: ctx.modulesFile?.prunedAt,
|
||||
wantedLockfile: result.newLockfile,
|
||||
})
|
||||
|
||||
@@ -16,6 +16,7 @@ const workspacePackages = {
|
||||
test('allProjectsAreUpToDate(): works with packages linked through the workspace protocol using relative path', async () => {
|
||||
expect(await allProjectsAreUpToDate([
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'bar',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
@@ -25,6 +26,7 @@ test('allProjectsAreUpToDate(): works with packages linked through the workspace
|
||||
rootDir: 'bar',
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'foo',
|
||||
manifest: fooManifest,
|
||||
rootDir: 'foo',
|
||||
@@ -55,6 +57,7 @@ test('allProjectsAreUpToDate(): works with packages linked through the workspace
|
||||
test('allProjectsAreUpToDate(): works with aliased local dependencies', async () => {
|
||||
expect(await allProjectsAreUpToDate([
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'bar',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
@@ -64,6 +67,7 @@ test('allProjectsAreUpToDate(): works with aliased local dependencies', async ()
|
||||
rootDir: 'bar',
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'foo',
|
||||
manifest: fooManifest,
|
||||
rootDir: 'foo',
|
||||
@@ -94,6 +98,7 @@ test('allProjectsAreUpToDate(): works with aliased local dependencies', async ()
|
||||
test('allProjectsAreUpToDate(): works with aliased local dependencies that specify versions', async () => {
|
||||
expect(await allProjectsAreUpToDate([
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'bar',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
@@ -103,6 +108,7 @@ test('allProjectsAreUpToDate(): works with aliased local dependencies that speci
|
||||
rootDir: 'bar',
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'foo',
|
||||
manifest: fooManifest,
|
||||
rootDir: 'foo',
|
||||
@@ -133,6 +139,7 @@ test('allProjectsAreUpToDate(): works with aliased local dependencies that speci
|
||||
test('allProjectsAreUpToDate(): returns false if the aliased dependency version is out of date', async () => {
|
||||
expect(await allProjectsAreUpToDate([
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'bar',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
@@ -142,6 +149,7 @@ test('allProjectsAreUpToDate(): returns false if the aliased dependency version
|
||||
rootDir: 'bar',
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'foo',
|
||||
manifest: fooManifest,
|
||||
rootDir: 'foo',
|
||||
@@ -174,6 +182,7 @@ test('allProjectsAreUpToDate(): use link and registry version if linkWorkspacePa
|
||||
await allProjectsAreUpToDate(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'bar',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
@@ -185,6 +194,7 @@ test('allProjectsAreUpToDate(): use link and registry version if linkWorkspacePa
|
||||
rootDir: 'bar',
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'bar2',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
@@ -194,11 +204,13 @@ test('allProjectsAreUpToDate(): use link and registry version if linkWorkspacePa
|
||||
rootDir: 'bar2',
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'foo',
|
||||
manifest: fooManifest,
|
||||
rootDir: 'foo',
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'foo2',
|
||||
manifest: {
|
||||
name: 'foo2',
|
||||
@@ -207,6 +219,7 @@ test('allProjectsAreUpToDate(): use link and registry version if linkWorkspacePa
|
||||
rootDir: 'foo2',
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'foo3',
|
||||
manifest: {
|
||||
name: 'foo3',
|
||||
@@ -261,6 +274,7 @@ test('allProjectsAreUpToDate(): use link and registry version if linkWorkspacePa
|
||||
test('allProjectsAreUpToDate(): returns false if dependenciesMeta differs', async () => {
|
||||
expect(await allProjectsAreUpToDate([
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'bar',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
@@ -275,6 +289,7 @@ test('allProjectsAreUpToDate(): returns false if dependenciesMeta differs', asyn
|
||||
rootDir: 'bar',
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'foo',
|
||||
manifest: fooManifest,
|
||||
rootDir: 'foo',
|
||||
@@ -305,6 +320,7 @@ test('allProjectsAreUpToDate(): returns false if dependenciesMeta differs', asyn
|
||||
test('allProjectsAreUpToDate(): returns true if dependenciesMeta matches', async () => {
|
||||
expect(await allProjectsAreUpToDate([
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'bar',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
@@ -319,6 +335,7 @@ test('allProjectsAreUpToDate(): returns true if dependenciesMeta matches', async
|
||||
rootDir: 'bar',
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
id: 'foo',
|
||||
manifest: fooManifest,
|
||||
rootDir: 'foo',
|
||||
|
||||
@@ -5,7 +5,7 @@ import rimraf from '@zkochan/rimraf'
|
||||
import clone from 'ramda/src/clone'
|
||||
import {
|
||||
addDependenciesToPackage,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import writeYamlFile from 'write-yaml-file'
|
||||
import { testDefaults } from './utils'
|
||||
@@ -27,23 +27,17 @@ test('installation breaks if the lockfile contains the wrong checksum', async ()
|
||||
corruptedLockfile.packages['/@pnpm.e2e/pkg-with-1-dep/100.0.0'].resolution['integrity'] = corruptedLockfile.packages['/@pnpm.e2e/dep-of-pkg-with-1-dep/100.0.0'].resolution['integrity']
|
||||
await writeYamlFile(WANTED_LOCKFILE, corruptedLockfile, { lineWidth: 1000 })
|
||||
|
||||
await expect(mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ frozenLockfile: true }))).rejects.toThrowError(/Package name mismatch found while reading/)
|
||||
await expect(mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true }))).rejects.toThrowError(/Package name mismatch found while reading/)
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults())
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults())
|
||||
|
||||
expect(await project.readLockfile()).toStrictEqual(correctLockfile)
|
||||
|
||||
@@ -52,14 +46,11 @@ test('installation breaks if the lockfile contains the wrong checksum', async ()
|
||||
|
||||
await rimraf('node_modules')
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ preferFrozenLockfile: false }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ preferFrozenLockfile: false }))
|
||||
|
||||
expect(await project.readLockfile()).toStrictEqual(correctLockfile)
|
||||
})
|
||||
@@ -82,25 +73,18 @@ test('installation breaks if the lockfile contains the wrong checksum and the st
|
||||
await writeYamlFile(WANTED_LOCKFILE, corruptedLockfile, { lineWidth: 1000 })
|
||||
|
||||
await expect(
|
||||
mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ frozenLockfile: true }, { retry: { retries: 0 } }))
|
||||
).rejects.toThrowError(/Got unexpected checksum/)
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({}, { retry: { retries: 0 } }))
|
||||
}, await testDefaults({ frozenLockfile: true }, { retry: { retries: 0 } }))
|
||||
).rejects.toThrowError(/Got unexpected checksum/)
|
||||
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({}, { retry: { retries: 0 } }))
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -113,14 +97,11 @@ test('installation breaks if the lockfile contains the wrong checksum and the st
|
||||
await rimraf('node_modules')
|
||||
|
||||
const reporter = jest.fn()
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ preferFrozenLockfile: false, reporter }, { retry: { retries: 0 } }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ preferFrozenLockfile: false, reporter }, { retry: { retries: 0 } }))
|
||||
|
||||
expect(reporter).toBeCalledWith(expect.objectContaining({
|
||||
level: 'warn',
|
||||
|
||||
@@ -7,6 +7,7 @@ test('cannot resolve peer dependency for top-level dependency', async () => {
|
||||
|
||||
const peerDependencyIssues = await getPeerDependencyIssues([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'ajv-keywords': '1.5.0',
|
||||
@@ -24,6 +25,7 @@ test('a conflict is detected when the same peer is required with ranges that do
|
||||
|
||||
const peerDependencyIssues = await getPeerDependencyIssues([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@pnpm.e2e/has-foo100-peer': '1.0.0',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { addDependenciesToPackage, install, mutateModules } from '@pnpm/core'
|
||||
import { addDependenciesToPackage, install, mutateModules, mutateModulesInSingleProject } from '@pnpm/core'
|
||||
import { prepareEmpty } from '@pnpm/prepare'
|
||||
import { addDistTag } from '@pnpm/registry-mock'
|
||||
import { sync as loadJsonFile } from 'load-json-file'
|
||||
@@ -107,32 +107,42 @@ test('adding a new dependency to one of the workspace projects', async () => {
|
||||
|
||||
let [{ manifest }] = await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-1',
|
||||
version: '1.0.0',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/bar': '100.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 1,
|
||||
manifest: {
|
||||
name: 'project-2',
|
||||
version: '1.0.0',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/foobarqar': '1.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
], await testDefaults({ nodeLinker: 'hoisted' }))
|
||||
], await testDefaults({
|
||||
allProjects: [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-1',
|
||||
version: '1.0.0',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/bar': '100.0.0',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 1,
|
||||
manifest: {
|
||||
name: 'project-2',
|
||||
version: '1.0.0',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/foobarqar': '1.0.0',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
],
|
||||
nodeLinker: 'hoisted',
|
||||
}))
|
||||
manifest = await addDependenciesToPackage(
|
||||
manifest,
|
||||
['is-negative@1.0.0'],
|
||||
@@ -181,21 +191,18 @@ test('run pre/postinstall scripts. bin files should be linked in a hoisted node_
|
||||
test('running install scripts in a workspace that has no root project', async () => {
|
||||
prepareEmpty()
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-1',
|
||||
version: '1.0.0',
|
||||
await mutateModulesInSingleProject({
|
||||
manifest: {
|
||||
name: 'project-1',
|
||||
version: '1.0.0',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/pre-and-postinstall-scripts-example': '1.0.0',
|
||||
},
|
||||
dependencies: {
|
||||
'@pnpm.e2e/pre-and-postinstall-scripts-example': '1.0.0',
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
], await testDefaults({ fastUnpack: false, nodeLinker: 'hoisted' }))
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
}, await testDefaults({ fastUnpack: false, nodeLinker: 'hoisted' }))
|
||||
|
||||
expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeTruthy()
|
||||
})
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
import { prepareEmpty } from '@pnpm/prepare'
|
||||
import {
|
||||
addDependenciesToPackage,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import sinon from 'sinon'
|
||||
import { testDefaults } from './../utils'
|
||||
@@ -20,14 +20,12 @@ test('uninstall package with no dependencies', async () => {
|
||||
)
|
||||
|
||||
const reporter = sinon.spy()
|
||||
manifest = (await mutateModules([
|
||||
{
|
||||
dependencyNames: ['is-negative'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ nodeLinker: 'hoisted', save: true, reporter })))[0].manifest
|
||||
manifest = (await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-negative'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ nodeLinker: 'hoisted', save: true, reporter }))).manifest
|
||||
|
||||
expect(reporter.calledWithMatch({
|
||||
initial: {
|
||||
@@ -80,14 +78,12 @@ test('uninstall package with dependencies and do not touch other deps', async ()
|
||||
['is-negative@2.1.0', 'camelcase-keys@3.0.0'],
|
||||
await testDefaults({ nodeLinker: 'hoisted', save: true })
|
||||
)
|
||||
manifest = (await mutateModules([
|
||||
{
|
||||
dependencyNames: ['camelcase-keys'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ nodeLinker: 'hoisted', pruneStore: true, save: true })))[0].manifest
|
||||
manifest = (await mutateModulesInSingleProject({
|
||||
dependencyNames: ['camelcase-keys'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ nodeLinker: 'hoisted', pruneStore: true, save: true }))).manifest
|
||||
|
||||
await project.storeHasNot('camelcase-keys', '3.0.0')
|
||||
await project.hasNot('camelcase-keys')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from 'path'
|
||||
import assertProject from '@pnpm/assert-project'
|
||||
import { addDependenciesToPackage, install, mutateModules, PackageManifest } from '@pnpm/core'
|
||||
import { addDependenciesToPackage, install, mutateModules, mutateModulesInSingleProject, PackageManifest } from '@pnpm/core'
|
||||
import { prepareEmpty, preparePackages } from '@pnpm/prepare'
|
||||
import { addDistTag, REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
|
||||
import rimraf from '@zkochan/rimraf'
|
||||
@@ -221,14 +221,12 @@ test('automatically install root peer dependencies', async () => {
|
||||
}
|
||||
|
||||
// The auto installed peer is not removed when a dependency is removed
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: ['is-odd'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ autoInstallPeers: true }))
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-odd'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ autoInstallPeers: true }))
|
||||
await project.hasNot('is-odd')
|
||||
await project.has('is-positive')
|
||||
await project.has('is-negative')
|
||||
@@ -251,28 +249,38 @@ test('automatically install peer dependency when it is a dev dependency in anoth
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-1',
|
||||
devDependencies: {
|
||||
'is-positive': '1.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-2',
|
||||
peerDependencies: {
|
||||
'is-positive': '1.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
], await testDefaults({ autoInstallPeers: true }))
|
||||
], await testDefaults({
|
||||
allProjects: [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-1',
|
||||
devDependencies: {
|
||||
'is-positive': '1.0.0',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-2',
|
||||
peerDependencies: {
|
||||
'is-positive': '1.0.0',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
],
|
||||
autoInstallPeers: true,
|
||||
}))
|
||||
|
||||
const project = assertProject(process.cwd())
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -289,57 +297,77 @@ test('auto install peer deps in a workspace. test #1', async () => {
|
||||
prepareEmpty()
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'root-project',
|
||||
devDependencies: {
|
||||
'@pnpm.e2e/abc-parent-with-ab': '1.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project',
|
||||
peerDependencies: {
|
||||
'@pnpm.e2e/abc-parent-with-ab': '1.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project'),
|
||||
},
|
||||
], await testDefaults({ autoInstallPeers: true }))
|
||||
], await testDefaults({
|
||||
autoInstallPeers: true,
|
||||
allProjects: [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'root-project',
|
||||
devDependencies: {
|
||||
'@pnpm.e2e/abc-parent-with-ab': '1.0.0',
|
||||
},
|
||||
},
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project',
|
||||
peerDependencies: {
|
||||
'@pnpm.e2e/abc-parent-with-ab': '1.0.0',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project'),
|
||||
},
|
||||
],
|
||||
}))
|
||||
})
|
||||
|
||||
test('auto install peer deps in a workspace. test #2', async () => {
|
||||
prepareEmpty()
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'root-project',
|
||||
devDependencies: {
|
||||
'@pnpm.e2e/abc-parent-with-ab': '1.0.0',
|
||||
'@pnpm.e2e/peer-c': '1.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project',
|
||||
peerDependencies: {
|
||||
'@pnpm.e2e/abc-parent-with-ab': '1.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project'),
|
||||
},
|
||||
], await testDefaults({ autoInstallPeers: true }))
|
||||
], await testDefaults({
|
||||
autoInstallPeers: true,
|
||||
allProjects: [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'root-project',
|
||||
devDependencies: {
|
||||
'@pnpm.e2e/abc-parent-with-ab': '1.0.0',
|
||||
'@pnpm.e2e/peer-c': '1.0.0',
|
||||
},
|
||||
},
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project',
|
||||
peerDependencies: {
|
||||
'@pnpm.e2e/abc-parent-with-ab': '1.0.0',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project'),
|
||||
},
|
||||
],
|
||||
}))
|
||||
})
|
||||
|
||||
// This test may be removed if autoInstallPeers will become true by default
|
||||
@@ -353,140 +381,152 @@ test('installation on a workspace with many complex circular dependencies does n
|
||||
prepareEmpty()
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project1',
|
||||
dependencies: {
|
||||
'@angular/common': '14.2.4',
|
||||
'@angular/core': '14.2.4',
|
||||
'@angular/forms': '14.2.4',
|
||||
'@angular/platform-browser': '14.2.4',
|
||||
'@angular/platform-browser-dynamic': '14.2.4',
|
||||
'@angular/router': '14.2.4',
|
||||
'@capacitor/app': '4.0.1',
|
||||
'@capacitor/core': '4.3.0',
|
||||
'@capacitor/haptics': '4.0.1',
|
||||
'@capacitor/keyboard': '4.0.1',
|
||||
'@capacitor/status-bar': '4.0.1',
|
||||
'@ionic/angular': '6.2.9',
|
||||
'@ionic/core': '6.2.9',
|
||||
ionicons: '6.0.3',
|
||||
'ng-particles': '3.3.3',
|
||||
rxjs: '7.5.7',
|
||||
tslib: '2.4.0',
|
||||
tsparticles: '2.3.4',
|
||||
'tsparticles-engine': '2.3.3',
|
||||
'tsparticles-interaction-external-attract': '2.3.3',
|
||||
'tsparticles-interaction-external-bounce': '2.3.3',
|
||||
'tsparticles-interaction-external-bubble': '2.3.3',
|
||||
'tsparticles-interaction-external-connect': '2.3.3',
|
||||
'tsparticles-interaction-external-grab': '2.3.3',
|
||||
'tsparticles-interaction-external-pause': '2.3.3',
|
||||
'tsparticles-interaction-external-push': '2.3.3',
|
||||
'tsparticles-interaction-external-remove': '2.3.3',
|
||||
'tsparticles-interaction-external-repulse': '2.3.4',
|
||||
'tsparticles-interaction-external-slow': '2.3.3',
|
||||
'tsparticles-interaction-external-trail': '2.3.3',
|
||||
'tsparticles-interaction-particles-attract': '2.3.3',
|
||||
'tsparticles-interaction-particles-collisions': '2.3.3',
|
||||
'tsparticles-interaction-particles-links': '2.3.3',
|
||||
'tsparticles-move-base': '2.3.3',
|
||||
'tsparticles-move-parallax': '2.3.3',
|
||||
'tsparticles-particles.js': '2.3.3',
|
||||
'tsparticles-plugin-absorbers': '2.3.4',
|
||||
'tsparticles-plugin-emitters': '2.3.4',
|
||||
'tsparticles-plugin-polygon-mask': '2.3.3',
|
||||
'tsparticles-shape-circle': '2.3.3',
|
||||
'tsparticles-shape-image': '2.3.3',
|
||||
'tsparticles-shape-line': '2.3.3',
|
||||
'tsparticles-shape-polygon': '2.3.3',
|
||||
'tsparticles-shape-square': '2.3.3',
|
||||
'tsparticles-shape-star': '2.3.3',
|
||||
'tsparticles-shape-text': '2.3.3',
|
||||
'tsparticles-slim': '2.3.4',
|
||||
'tsparticles-updater-angle': '2.3.3',
|
||||
'tsparticles-updater-color': '2.3.3',
|
||||
'tsparticles-updater-destroy': '2.3.3',
|
||||
'tsparticles-updater-life': '2.3.3',
|
||||
'tsparticles-updater-opacity': '2.3.3',
|
||||
'tsparticles-updater-out-modes': '2.3.3',
|
||||
'tsparticles-updater-roll': '2.3.3',
|
||||
'tsparticles-updater-size': '2.3.3',
|
||||
'tsparticles-updater-stroke-color': '2.3.3',
|
||||
'tsparticles-updater-tilt': '2.3.3',
|
||||
'tsparticles-updater-twinkle': '2.3.3',
|
||||
'tsparticles-updater-wobble': '2.3.3',
|
||||
'zone.js': '0.11.8',
|
||||
},
|
||||
devDependencies: {
|
||||
'@angular-devkit/build-angular': '14.2.4',
|
||||
'@angular-eslint/builder': '14.1.2',
|
||||
'@angular-eslint/eslint-plugin': '14.1.2',
|
||||
'@angular-eslint/eslint-plugin-template': '14.1.2',
|
||||
'@angular-eslint/template-parser': '14.1.2',
|
||||
'@angular/cli': '14.2.4',
|
||||
'@angular/compiler': '14.2.4',
|
||||
'@angular/compiler-cli': '14.2.4',
|
||||
'@angular/language-service': '14.2.4',
|
||||
'@capacitor/cli': '4.3.0',
|
||||
'@ionic/angular-toolkit': '7.0.0',
|
||||
'@types/jasmine': '4.3.0',
|
||||
'@types/jasminewd2': '2.0.10',
|
||||
'@types/node': '18.7.23',
|
||||
'@typescript-eslint/eslint-plugin': '5.38.1',
|
||||
'@typescript-eslint/parser': '5.38.1',
|
||||
eslint: '8.24.0',
|
||||
'eslint-plugin-import': '2.26.0',
|
||||
'eslint-plugin-jsdoc': '39.3.6',
|
||||
'eslint-plugin-prefer-arrow': '1.2.3',
|
||||
'jasmine-core': '4.4.0',
|
||||
'jasmine-spec-reporter': '7.0.0',
|
||||
karma: '6.4.1',
|
||||
'karma-chrome-launcher': '3.1.1',
|
||||
'karma-coverage': '2.2.0',
|
||||
'karma-coverage-istanbul-reporter': '3.0.3',
|
||||
'karma-jasmine': '5.1.0',
|
||||
'karma-jasmine-html-reporter': '2.0.0',
|
||||
protractor: '7.0.0',
|
||||
'ts-node': '10.9.1',
|
||||
typescript: '4.8.4',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project2',
|
||||
devDependencies: {
|
||||
'@typescript-eslint/eslint-plugin': '5.38.1',
|
||||
'@typescript-eslint/parser': '5.38.1',
|
||||
copyfiles: '2.4.1',
|
||||
enzyme: '3.11.0',
|
||||
'enzyme-adapter-preact-pure': '4.0.1',
|
||||
eslint: '8.24.0',
|
||||
'eslint-config-preact': '1.3.0',
|
||||
'eslint-config-prettier': '8.5.0',
|
||||
'eslint-plugin-react-hooks': '4.6.0',
|
||||
'identity-obj-proxy': '3.0.0',
|
||||
'preact-cli': '3.4.1',
|
||||
prettier: '2.7.1',
|
||||
'sirv-cli': '2.0.2',
|
||||
},
|
||||
dependencies: {
|
||||
preact: '10.11.0',
|
||||
'preact-particles': '2.3.3',
|
||||
'preact-render-to-string': '5.2.4',
|
||||
'preact-router': '4.1.0',
|
||||
tsparticles: '2.3.4',
|
||||
'tsparticles-engine': '2.3.3',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project2'),
|
||||
},
|
||||
], await testDefaults({ autoInstallPeers: true, ignoreScripts: true, lockfileOnly: true }))
|
||||
], await testDefaults({
|
||||
autoInstallPeers: true,
|
||||
ignoreScripts: true,
|
||||
lockfileOnly: true,
|
||||
allProjects: [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project1',
|
||||
dependencies: {
|
||||
'@angular/common': '14.2.4',
|
||||
'@angular/core': '14.2.4',
|
||||
'@angular/forms': '14.2.4',
|
||||
'@angular/platform-browser': '14.2.4',
|
||||
'@angular/platform-browser-dynamic': '14.2.4',
|
||||
'@angular/router': '14.2.4',
|
||||
'@capacitor/app': '4.0.1',
|
||||
'@capacitor/core': '4.3.0',
|
||||
'@capacitor/haptics': '4.0.1',
|
||||
'@capacitor/keyboard': '4.0.1',
|
||||
'@capacitor/status-bar': '4.0.1',
|
||||
'@ionic/angular': '6.2.9',
|
||||
'@ionic/core': '6.2.9',
|
||||
ionicons: '6.0.3',
|
||||
'ng-particles': '3.3.3',
|
||||
rxjs: '7.5.7',
|
||||
tslib: '2.4.0',
|
||||
tsparticles: '2.3.4',
|
||||
'tsparticles-engine': '2.3.3',
|
||||
'tsparticles-interaction-external-attract': '2.3.3',
|
||||
'tsparticles-interaction-external-bounce': '2.3.3',
|
||||
'tsparticles-interaction-external-bubble': '2.3.3',
|
||||
'tsparticles-interaction-external-connect': '2.3.3',
|
||||
'tsparticles-interaction-external-grab': '2.3.3',
|
||||
'tsparticles-interaction-external-pause': '2.3.3',
|
||||
'tsparticles-interaction-external-push': '2.3.3',
|
||||
'tsparticles-interaction-external-remove': '2.3.3',
|
||||
'tsparticles-interaction-external-repulse': '2.3.4',
|
||||
'tsparticles-interaction-external-slow': '2.3.3',
|
||||
'tsparticles-interaction-external-trail': '2.3.3',
|
||||
'tsparticles-interaction-particles-attract': '2.3.3',
|
||||
'tsparticles-interaction-particles-collisions': '2.3.3',
|
||||
'tsparticles-interaction-particles-links': '2.3.3',
|
||||
'tsparticles-move-base': '2.3.3',
|
||||
'tsparticles-move-parallax': '2.3.3',
|
||||
'tsparticles-particles.js': '2.3.3',
|
||||
'tsparticles-plugin-absorbers': '2.3.4',
|
||||
'tsparticles-plugin-emitters': '2.3.4',
|
||||
'tsparticles-plugin-polygon-mask': '2.3.3',
|
||||
'tsparticles-shape-circle': '2.3.3',
|
||||
'tsparticles-shape-image': '2.3.3',
|
||||
'tsparticles-shape-line': '2.3.3',
|
||||
'tsparticles-shape-polygon': '2.3.3',
|
||||
'tsparticles-shape-square': '2.3.3',
|
||||
'tsparticles-shape-star': '2.3.3',
|
||||
'tsparticles-shape-text': '2.3.3',
|
||||
'tsparticles-slim': '2.3.4',
|
||||
'tsparticles-updater-angle': '2.3.3',
|
||||
'tsparticles-updater-color': '2.3.3',
|
||||
'tsparticles-updater-destroy': '2.3.3',
|
||||
'tsparticles-updater-life': '2.3.3',
|
||||
'tsparticles-updater-opacity': '2.3.3',
|
||||
'tsparticles-updater-out-modes': '2.3.3',
|
||||
'tsparticles-updater-roll': '2.3.3',
|
||||
'tsparticles-updater-size': '2.3.3',
|
||||
'tsparticles-updater-stroke-color': '2.3.3',
|
||||
'tsparticles-updater-tilt': '2.3.3',
|
||||
'tsparticles-updater-twinkle': '2.3.3',
|
||||
'tsparticles-updater-wobble': '2.3.3',
|
||||
'zone.js': '0.11.8',
|
||||
},
|
||||
devDependencies: {
|
||||
'@angular-devkit/build-angular': '14.2.4',
|
||||
'@angular-eslint/builder': '14.1.2',
|
||||
'@angular-eslint/eslint-plugin': '14.1.2',
|
||||
'@angular-eslint/eslint-plugin-template': '14.1.2',
|
||||
'@angular-eslint/template-parser': '14.1.2',
|
||||
'@angular/cli': '14.2.4',
|
||||
'@angular/compiler': '14.2.4',
|
||||
'@angular/compiler-cli': '14.2.4',
|
||||
'@angular/language-service': '14.2.4',
|
||||
'@capacitor/cli': '4.3.0',
|
||||
'@ionic/angular-toolkit': '7.0.0',
|
||||
'@types/jasmine': '4.3.0',
|
||||
'@types/jasminewd2': '2.0.10',
|
||||
'@types/node': '18.7.23',
|
||||
'@typescript-eslint/eslint-plugin': '5.38.1',
|
||||
'@typescript-eslint/parser': '5.38.1',
|
||||
eslint: '8.24.0',
|
||||
'eslint-plugin-import': '2.26.0',
|
||||
'eslint-plugin-jsdoc': '39.3.6',
|
||||
'eslint-plugin-prefer-arrow': '1.2.3',
|
||||
'jasmine-core': '4.4.0',
|
||||
'jasmine-spec-reporter': '7.0.0',
|
||||
karma: '6.4.1',
|
||||
'karma-chrome-launcher': '3.1.1',
|
||||
'karma-coverage': '2.2.0',
|
||||
'karma-coverage-istanbul-reporter': '3.0.3',
|
||||
'karma-jasmine': '5.1.0',
|
||||
'karma-jasmine-html-reporter': '2.0.0',
|
||||
protractor: '7.0.0',
|
||||
'ts-node': '10.9.1',
|
||||
typescript: '4.8.4',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project2',
|
||||
devDependencies: {
|
||||
'@typescript-eslint/eslint-plugin': '5.38.1',
|
||||
'@typescript-eslint/parser': '5.38.1',
|
||||
copyfiles: '2.4.1',
|
||||
enzyme: '3.11.0',
|
||||
'enzyme-adapter-preact-pure': '4.0.1',
|
||||
eslint: '8.24.0',
|
||||
'eslint-config-preact': '1.3.0',
|
||||
'eslint-config-prettier': '8.5.0',
|
||||
'eslint-plugin-react-hooks': '4.6.0',
|
||||
'identity-obj-proxy': '3.0.0',
|
||||
'preact-cli': '3.4.1',
|
||||
prettier: '2.7.1',
|
||||
'sirv-cli': '2.0.2',
|
||||
},
|
||||
dependencies: {
|
||||
preact: '10.11.0',
|
||||
'preact-particles': '2.3.3',
|
||||
'preact-render-to-string': '5.2.4',
|
||||
'preact-router': '4.1.0',
|
||||
tsparticles: '2.3.4',
|
||||
'tsparticles-engine': '2.3.3',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project2'),
|
||||
},
|
||||
],
|
||||
}))
|
||||
})
|
||||
|
||||
test('do not override the direct dependency with an auto installed peer dependency', async () => {
|
||||
|
||||
@@ -79,35 +79,14 @@ test('--fix-lockfile should preserve all locked dependencies version', async ()
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'root',
|
||||
version: '1.0.0',
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('.'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-1',
|
||||
version: '1.0.0',
|
||||
dependencies: {
|
||||
'@babel/runtime-corejs3': '7.15.3',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-3',
|
||||
version: '1.0.0',
|
||||
dependencies: {
|
||||
'@babel/runtime-corejs3': '7.15.4',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
@@ -177,7 +156,42 @@ test('--fix-lockfile should preserve all locked dependencies version', async ()
|
||||
},
|
||||
}, { lineWidth: 1000 })
|
||||
|
||||
await mutateModules(importers, await testDefaults({ fixLockfile: true, lockfileOnly: true }))
|
||||
await mutateModules(importers, await testDefaults({
|
||||
fixLockfile: true,
|
||||
lockfileOnly: true,
|
||||
allProjects: [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'root',
|
||||
version: '1.0.0',
|
||||
},
|
||||
rootDir: path.resolve('.'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-1',
|
||||
version: '1.0.0',
|
||||
dependencies: {
|
||||
'@babel/runtime-corejs3': '7.15.3',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-3',
|
||||
version: '1.0.0',
|
||||
dependencies: {
|
||||
'@babel/runtime-corejs3': '7.15.4',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
],
|
||||
}))
|
||||
|
||||
const lockfile: Lockfile = await readYamlFile(WANTED_LOCKFILE)
|
||||
|
||||
|
||||
@@ -53,40 +53,49 @@ test(`frozen-lockfile: fail on a shared ${WANTED_LOCKFILE} that does not satisfy
|
||||
|
||||
const projects: MutatedProject[] = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'p1',
|
||||
|
||||
dependencies: {
|
||||
'is-positive': '^3.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('p1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'p2',
|
||||
|
||||
dependencies: {
|
||||
'is-negative': '1.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('p2'),
|
||||
},
|
||||
]
|
||||
await mutateModules(projects, await testDefaults())
|
||||
const project1 = {
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'p1',
|
||||
|
||||
projects[0].manifest = {
|
||||
dependencies: {
|
||||
'is-positive': '^3.0.0',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('p1'),
|
||||
}
|
||||
const project2 = {
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'p2',
|
||||
|
||||
dependencies: {
|
||||
'is-negative': '1.0.0',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('p2'),
|
||||
}
|
||||
await mutateModules(projects, await testDefaults({
|
||||
allProjects: [project1, project2],
|
||||
}))
|
||||
|
||||
project1.manifest = {
|
||||
...project1.manifest,
|
||||
dependencies: {
|
||||
'is-positive': '^3.1.0',
|
||||
},
|
||||
}
|
||||
|
||||
await expect(
|
||||
mutateModules(projects, await testDefaults({ frozenLockfile: true }))
|
||||
mutateModules(projects, await testDefaults({ frozenLockfile: true, allProjects: [project1, project2] }))
|
||||
).rejects.toThrow(`Cannot install with "frozen-lockfile" because ${WANTED_LOCKFILE} is not up to date with p1${path.sep}package.json`)
|
||||
})
|
||||
|
||||
@@ -227,6 +236,16 @@ test('prefer-frozen-lockfile: should prefer frozen-lockfile when package has lin
|
||||
])
|
||||
|
||||
const mutatedProjects: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('p1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('p2'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
@@ -236,7 +255,6 @@ test('prefer-frozen-lockfile: should prefer frozen-lockfile when package has lin
|
||||
p2: 'link:../p2',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('p1'),
|
||||
},
|
||||
{
|
||||
@@ -248,14 +266,14 @@ test('prefer-frozen-lockfile: should prefer frozen-lockfile when package has lin
|
||||
'is-negative': '1.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('p2'),
|
||||
},
|
||||
]
|
||||
await mutateModules(mutatedProjects, await testDefaults())
|
||||
await mutateModules(mutatedProjects, await testDefaults({ allProjects }))
|
||||
|
||||
const reporter = sinon.spy()
|
||||
await mutateModules(mutatedProjects, await testDefaults({
|
||||
allProjects,
|
||||
preferFrozenLockfile: true,
|
||||
reporter,
|
||||
}))
|
||||
|
||||
@@ -90,24 +90,35 @@ test('install a workspace with git-branch-lockfile = true', async () => {
|
||||
|
||||
const opts = await testDefaults({
|
||||
useGitBranchLockfile: true,
|
||||
allProjects: [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: rootManifest,
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: rootManifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
install,
|
||||
MutatedProject,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import rimraf from '@zkochan/rimraf'
|
||||
import resolveLinkTarget from 'resolve-link-target'
|
||||
@@ -85,14 +86,12 @@ test('should remove hoisted dependencies', async () => {
|
||||
const project = prepareEmpty()
|
||||
|
||||
const manifest = await addDependenciesToPackage({}, ['express'], await testDefaults({ fastUnpack: false, hoistPattern: '*' }))
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: ['express'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ hoistPattern: '*' }))
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['express'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ hoistPattern: '*' }))
|
||||
|
||||
await project.hasNot('express')
|
||||
await project.hasNot('.pnpm/node_modules/debug')
|
||||
@@ -116,14 +115,12 @@ test('should rehoist when uninstalling a package', async () => {
|
||||
// this installs debug@3.1.0 and express@4.16.0
|
||||
const manifest = await addDependenciesToPackage({}, ['debug@3.1.0', 'express@4.16.0'], await testDefaults({ fastUnpack: false, hoistPattern: '*' }))
|
||||
// uninstall debug@3.1.0 to check if debug@2.6.9 gets reflattened
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: ['debug'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ hoistPattern: '*' }))
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['debug'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ hoistPattern: '*' }))
|
||||
|
||||
expect(project.requireModule('.pnpm/node_modules/debug/package.json').version).toEqual('2.6.9')
|
||||
expect(project.requireModule('express/package.json').version).toEqual('4.16.0')
|
||||
@@ -226,14 +223,12 @@ test('should remove aliased hoisted dependencies', async () => {
|
||||
const project = prepareEmpty()
|
||||
|
||||
const manifest = await addDependenciesToPackage({}, ['@pnpm.e2e/pkg-with-1-aliased-dep'], await testDefaults({ hoistPattern: '*' }))
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: ['@pnpm.e2e/pkg-with-1-aliased-dep'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ hoistPattern: '*' }))
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['@pnpm.e2e/pkg-with-1-aliased-dep'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ hoistPattern: '*' }))
|
||||
|
||||
await project.hasNot('@pnpm.e2e/pkg-with-1-aliased-dep')
|
||||
await project.hasNot('@pnpm.e2e/dep-of-pkg-with-1-dep')
|
||||
@@ -305,14 +300,12 @@ test('should hoist correctly peer dependencies', async () => {
|
||||
test('should uninstall correctly peer dependencies', async () => {
|
||||
prepareEmpty()
|
||||
const manifest = await addDependenciesToPackage({}, ['@pnpm.e2e/using-ajv'], await testDefaults({ hoistPattern: '*' }))
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: ['@pnpm.e2e/using-ajv'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ hoistPattern: '*' }))
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['@pnpm.e2e/using-ajv'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ hoistPattern: '*' }))
|
||||
|
||||
// symlink to peer dependency is deleted
|
||||
expect(() => fs.lstatSync('node_modules/ajv-keywords')).toThrow()
|
||||
@@ -345,20 +338,28 @@ test('hoist-pattern: hoist all dependencies to the virtual store node_modules',
|
||||
])
|
||||
|
||||
const mutatedProjects: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('package'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: workspaceRootManifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: workspacePackageManifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('package'),
|
||||
},
|
||||
]
|
||||
await mutateModules(mutatedProjects, await testDefaults({ hoistPattern: '*' }))
|
||||
await mutateModules(mutatedProjects, await testDefaults({ allProjects, hoistPattern: '*' }))
|
||||
|
||||
await projects['root'].has('@pnpm.e2e/pkg-with-1-dep')
|
||||
await projects['root'].has('.pnpm/node_modules/@pnpm.e2e/dep-of-pkg-with-1-dep')
|
||||
@@ -376,7 +377,7 @@ test('hoist-pattern: hoist all dependencies to the virtual store node_modules',
|
||||
await rimraf('node_modules')
|
||||
await rimraf('package/node_modules')
|
||||
|
||||
await mutateModules(mutatedProjects, await testDefaults({ frozenLockfile: true, hoistPattern: '*' }))
|
||||
await mutateModules(mutatedProjects, await testDefaults({ allProjects, frozenLockfile: true, hoistPattern: '*' }))
|
||||
|
||||
await projects['root'].has('@pnpm.e2e/pkg-with-1-dep')
|
||||
await projects['root'].has('.pnpm/node_modules/@pnpm.e2e/dep-of-pkg-with-1-dep')
|
||||
@@ -421,20 +422,28 @@ test('hoist when updating in one of the workspace projects', async () => {
|
||||
])
|
||||
|
||||
const mutatedProjects: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('package'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: workspaceRootManifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: workspacePackageManifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('package'),
|
||||
},
|
||||
]
|
||||
await mutateModules(mutatedProjects, await testDefaults({ hoistPattern: '*' }))
|
||||
await mutateModules(mutatedProjects, await testDefaults({ allProjects, hoistPattern: '*' }))
|
||||
|
||||
const rootModules = assertProject(process.cwd())
|
||||
{
|
||||
@@ -451,7 +460,7 @@ test('hoist when updating in one of the workspace projects', async () => {
|
||||
dependencySelectors: ['@pnpm.e2e/foo@100.1.0'],
|
||||
mutation: 'installSome',
|
||||
},
|
||||
], await testDefaults({ hoistPattern: '*', pruneLockfileImporters: false }))
|
||||
], await testDefaults({ allProjects, hoistPattern: '*', pruneLockfileImporters: false }))
|
||||
|
||||
const lockfile = await rootModules.readCurrentLockfile()
|
||||
|
||||
@@ -485,14 +494,11 @@ test('should recreate node_modules with hoisting', async () => {
|
||||
expect(modulesManifest?.hoistedDependencies).toStrictEqual({})
|
||||
}
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ hoistPattern: '*' }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ hoistPattern: '*' }))
|
||||
|
||||
await project.has('@pnpm.e2e/pkg-with-1-dep')
|
||||
await project.has('.pnpm/node_modules/@pnpm.e2e/dep-of-pkg-with-1-dep')
|
||||
@@ -567,13 +573,22 @@ test('hoist packages which is in the dependencies tree of the selected projects'
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('.'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'root',
|
||||
version: '1.0.0',
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('.'),
|
||||
},
|
||||
{
|
||||
@@ -585,7 +600,6 @@ test('hoist packages which is in the dependencies tree of the selected projects'
|
||||
'is-positive': '3.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
@@ -632,7 +646,7 @@ test('hoist packages which is in the dependencies tree of the selected projects'
|
||||
},
|
||||
}, { lineWidth: 1000 })
|
||||
|
||||
await mutateModules(importers, await testDefaults({ hoistPattern: '*' }))
|
||||
await mutateModules(importers, await testDefaults({ allProjects, hoistPattern: '*' }))
|
||||
|
||||
await root.has('.pnpm/node_modules/is-positive')
|
||||
const { version } = root.requireModule('.pnpm/node_modules/is-positive/package.json')
|
||||
@@ -655,21 +669,6 @@ test('only hoist packages which is in the dependencies tree of the selected proj
|
||||
},
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project-2',
|
||||
version: '1.0.0',
|
||||
dependencies: {
|
||||
'@babel/runtime-corejs3': '7.15.4',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
|
||||
await writeYamlFile(WANTED_LOCKFILE, {
|
||||
lockfileVersion: 5.3,
|
||||
importers: {
|
||||
@@ -729,7 +728,17 @@ test('only hoist packages which is in the dependencies tree of the selected proj
|
||||
},
|
||||
}, { lineWidth: 1000 })
|
||||
|
||||
await mutateModules(importers, await testDefaults({ hoistPattern: '*' }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest: {
|
||||
name: 'project-2',
|
||||
version: '1.0.0',
|
||||
dependencies: {
|
||||
'@babel/runtime-corejs3': '7.15.4',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
}, await testDefaults({ hoistPattern: '*' }))
|
||||
|
||||
await root.has('.pnpm/node_modules/@babel/runtime-corejs3')
|
||||
const { version: runtimeVersion } = root.requireModule('.pnpm/node_modules/@babel/runtime-corejs3/package.json')
|
||||
|
||||
@@ -68,22 +68,33 @@ test('inject local packages', async () => {
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project3Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
@@ -108,6 +119,7 @@ test('inject local packages', async () => {
|
||||
},
|
||||
}
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
workspacePackages,
|
||||
}))
|
||||
|
||||
@@ -175,6 +187,7 @@ test('inject local packages', async () => {
|
||||
await rimraf('project-3/node_modules')
|
||||
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
frozenLockfile: true,
|
||||
workspacePackages,
|
||||
}))
|
||||
@@ -192,8 +205,8 @@ test('inject local packages', async () => {
|
||||
expect(fs.readdirSync('node_modules/.pnpm').length).toBe(8)
|
||||
|
||||
// The injected project is updated when one of its dependencies needs to be updated
|
||||
importers[0].manifest.dependencies!['is-negative'] = '2.0.0'
|
||||
await mutateModules(importers, await testDefaults({ workspacePackages }))
|
||||
allProjects[0].manifest.dependencies!['is-negative'] = '2.0.0'
|
||||
await mutateModules(importers, await testDefaults({ allProjects, workspacePackages }))
|
||||
{
|
||||
const lockfile = await rootModules.readLockfile()
|
||||
expect(lockfile.importers['project-2'].dependenciesMeta).toEqual({
|
||||
@@ -285,22 +298,33 @@ test('inject local packages declared via file protocol', async () => {
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project3Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
@@ -325,6 +349,7 @@ test('inject local packages declared via file protocol', async () => {
|
||||
},
|
||||
}
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
workspacePackages,
|
||||
}))
|
||||
|
||||
@@ -392,6 +417,7 @@ test('inject local packages declared via file protocol', async () => {
|
||||
await rimraf('project-3/node_modules')
|
||||
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
frozenLockfile: true,
|
||||
workspacePackages,
|
||||
}))
|
||||
@@ -409,9 +435,9 @@ test('inject local packages declared via file protocol', async () => {
|
||||
expect(fs.readdirSync('node_modules/.pnpm').length).toBe(8)
|
||||
|
||||
// The injected project is updated when one of its dependencies needs to be updated
|
||||
importers[0].manifest.dependencies!['is-negative'] = '2.0.0'
|
||||
writeJsonFile('project-1/package.json', importers[0].manifest)
|
||||
await mutateModules(importers, await testDefaults({ workspacePackages }))
|
||||
allProjects[0].manifest.dependencies!['is-negative'] = '2.0.0'
|
||||
writeJsonFile('project-1/package.json', allProjects[0].manifest)
|
||||
await mutateModules(importers, await testDefaults({ allProjects, workspacePackages }))
|
||||
{
|
||||
const lockfile = await rootModules.readLockfile()
|
||||
expect(lockfile.importers['project-2'].dependenciesMeta).toEqual({
|
||||
@@ -493,22 +519,33 @@ test('inject local packages when the file protocol is used', async () => {
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project3Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
@@ -533,6 +570,7 @@ test('inject local packages when the file protocol is used', async () => {
|
||||
},
|
||||
}
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
workspacePackages,
|
||||
}))
|
||||
|
||||
@@ -595,6 +633,7 @@ test('inject local packages when the file protocol is used', async () => {
|
||||
await rimraf('project-3/node_modules')
|
||||
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
frozenLockfile: true,
|
||||
workspacePackages,
|
||||
}))
|
||||
@@ -612,9 +651,12 @@ test('inject local packages when the file protocol is used', async () => {
|
||||
expect(fs.readdirSync('node_modules/.pnpm').length).toBe(8)
|
||||
|
||||
// The injected project is updated when one of its dependencies needs to be updated
|
||||
importers[0].manifest.dependencies!['is-negative'] = '2.0.0'
|
||||
writeJsonFile('project-1/package.json', importers[0].manifest)
|
||||
await mutateModules(importers, await testDefaults({ workspacePackages }))
|
||||
allProjects[0].manifest.dependencies!['is-negative'] = '2.0.0'
|
||||
writeJsonFile('project-1/package.json', allProjects[0].manifest)
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
workspacePackages,
|
||||
}))
|
||||
{
|
||||
const lockfile = await rootModules.readLockfile()
|
||||
expect(lockfile.packages['file:project-1_is-positive@1.0.0']).toEqual({
|
||||
@@ -683,16 +725,24 @@ test('inject local packages and relink them after build', async () => {
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
@@ -711,6 +761,7 @@ test('inject local packages and relink them after build', async () => {
|
||||
},
|
||||
}
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
workspacePackages,
|
||||
}))
|
||||
|
||||
@@ -754,6 +805,7 @@ test('inject local packages and relink them after build', async () => {
|
||||
await rimraf('project-2/node_modules')
|
||||
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
frozenLockfile: true,
|
||||
workspacePackages,
|
||||
}))
|
||||
@@ -805,20 +857,28 @@ test('inject local packages and relink them after build (file protocol is used)'
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
await mutateModules(importers, await testDefaults())
|
||||
await mutateModules(importers, await testDefaults({ allProjects }))
|
||||
|
||||
await projects['project-1'].has('is-negative')
|
||||
await projects['project-1'].has('@pnpm.e2e/dep-of-pkg-with-1-dep')
|
||||
@@ -855,6 +915,7 @@ test('inject local packages and relink them after build (file protocol is used)'
|
||||
await rimraf('project-2/node_modules')
|
||||
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
frozenLockfile: true,
|
||||
}))
|
||||
|
||||
@@ -927,22 +988,33 @@ test('inject local packages when node-linker is hoisted', async () => {
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project3Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
@@ -967,6 +1039,7 @@ test('inject local packages when node-linker is hoisted', async () => {
|
||||
},
|
||||
}
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
nodeLinker: 'hoisted',
|
||||
workspacePackages,
|
||||
}))
|
||||
@@ -1080,22 +1153,33 @@ test('inject local packages when node-linker is hoisted and dependenciesMeta is
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project3Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
@@ -1120,6 +1204,7 @@ test('inject local packages when node-linker is hoisted and dependenciesMeta is
|
||||
},
|
||||
}
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
nodeLinker: 'hoisted',
|
||||
workspacePackages,
|
||||
hooks: {
|
||||
@@ -1248,22 +1333,33 @@ test('peer dependency of injected project should be resolved correctly', async (
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project3Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-3'),
|
||||
},
|
||||
]
|
||||
@@ -1288,6 +1384,7 @@ test('peer dependency of injected project should be resolved correctly', async (
|
||||
},
|
||||
}
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
nodeLinker: 'hoisted',
|
||||
workspacePackages,
|
||||
}))
|
||||
@@ -1336,16 +1433,24 @@ test('do not modify the manifest of the injected workpspace project', async () =
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
@@ -1364,6 +1469,7 @@ test('do not modify the manifest of the injected workpspace project', async () =
|
||||
},
|
||||
}
|
||||
const [project1] = await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
workspacePackages,
|
||||
}))
|
||||
expect(project1.manifest).toStrictEqual({
|
||||
|
||||
@@ -5,7 +5,7 @@ import { prepareEmpty } from '@pnpm/prepare'
|
||||
import {
|
||||
addDependenciesToPackage,
|
||||
install,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import rimraf from '@zkochan/rimraf'
|
||||
import isWindows from 'is-windows'
|
||||
@@ -145,22 +145,19 @@ test('INIT_CWD is always set to lockfile directory', async () => {
|
||||
const rootDir = process.cwd()
|
||||
await fs.mkdir('subd')
|
||||
process.chdir('subd')
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
mutation: 'install',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'json-append': '1.1.1',
|
||||
'@pnpm.e2e/write-lifecycle-env': '1.0.0',
|
||||
},
|
||||
scripts: {
|
||||
install: 'node -e "process.stdout.write(process.env.INIT_CWD)" | json-append output.json',
|
||||
},
|
||||
await mutateModulesInSingleProject({
|
||||
mutation: 'install',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'json-append': '1.1.1',
|
||||
'@pnpm.e2e/write-lifecycle-env': '1.0.0',
|
||||
},
|
||||
scripts: {
|
||||
install: 'node -e "process.stdout.write(process.env.INIT_CWD)" | json-append output.json',
|
||||
},
|
||||
rootDir,
|
||||
},
|
||||
], await testDefaults({
|
||||
rootDir,
|
||||
}, await testDefaults({
|
||||
fastUnpack: false,
|
||||
lockfileDir: rootDir,
|
||||
}))
|
||||
@@ -297,17 +294,11 @@ test('lifecycle scripts run before linking bins', async () => {
|
||||
|
||||
await rimraf('node_modules')
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ frozenLockfile: true })
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true }))
|
||||
|
||||
await project.isExecutable('.bin/cmd1')
|
||||
await project.isExecutable('.bin/cmd2')
|
||||
@@ -324,17 +315,11 @@ test('hoisting does not fail on commands that will be created by lifecycle scrip
|
||||
// Testing the same with headless installation
|
||||
await rimraf('node_modules')
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ frozenLockfile: true, hoistPattern: '*' })
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true, hoistPattern: '*' }))
|
||||
|
||||
// await project.isExecutable('.pnpm/node_modules/.bin/cmd1')
|
||||
// await project.isExecutable('.pnpm/node_modules/.bin/cmd2')
|
||||
@@ -362,17 +347,11 @@ test('bins are linked even if lifecycle scripts are ignored', async () => {
|
||||
|
||||
await rimraf('node_modules')
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ frozenLockfile: true, ignoreScripts: true })
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true, ignoreScripts: true }))
|
||||
|
||||
await project.isExecutable('.bin/peer-with-bin')
|
||||
await project.isExecutable('@pnpm.e2e/pkg-with-peer-having-bin/node_modules/.bin/hello-world-js-bin')
|
||||
@@ -397,17 +376,11 @@ test('dependency should not be added to current lockfile if it was not built suc
|
||||
)
|
||||
|
||||
await expect(
|
||||
mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ frozenLockfile: true })
|
||||
)
|
||||
mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true }))
|
||||
).rejects.toThrow()
|
||||
|
||||
expect(await project.readCurrentLockfile()).toBeFalsy()
|
||||
@@ -504,14 +477,11 @@ test('lockfile is updated if neverBuiltDependencies is changed', async () => {
|
||||
}
|
||||
|
||||
const neverBuiltDependencies = ['@pnpm.e2e/pre-and-postinstall-scripts-example']
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ neverBuiltDependencies }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ neverBuiltDependencies }))
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -536,14 +506,11 @@ test('lockfile is updated if onlyBuiltDependencies is changed', async () => {
|
||||
}
|
||||
|
||||
const onlyBuiltDependencies: string[] = []
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ onlyBuiltDependencies }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ onlyBuiltDependencies }))
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -553,14 +520,11 @@ test('lockfile is updated if onlyBuiltDependencies is changed', async () => {
|
||||
}
|
||||
|
||||
onlyBuiltDependencies.push('@pnpm.e2e/pre-and-postinstall-scripts-example')
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ onlyBuiltDependencies }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ onlyBuiltDependencies }))
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -590,31 +554,19 @@ test('lifecycle scripts run after linking root dependencies', async () => {
|
||||
},
|
||||
}
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ fastUnpack: false })
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ fastUnpack: false }))
|
||||
|
||||
await rimraf('node_modules')
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ fastUnpack: false, frozenLockfile: true })
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ fastUnpack: false, frozenLockfile: true }))
|
||||
|
||||
// if there was no exception, the test passed
|
||||
})
|
||||
|
||||
@@ -8,7 +8,7 @@ import fixtures from '@pnpm/test-fixtures'
|
||||
import {
|
||||
addDependenciesToPackage,
|
||||
install,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import rimraf from '@zkochan/rimraf'
|
||||
import normalizePath from 'normalize-path'
|
||||
@@ -212,14 +212,11 @@ test('do not update deps when installing in a project that has local tarball dep
|
||||
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-a', version: '1.0.1', distTag: 'latest' })
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults())
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults())
|
||||
|
||||
const latestLockfile = await project.readLockfile()
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Lockfile } from '@pnpm/lockfile-file'
|
||||
import { prepareEmpty } from '@pnpm/prepare'
|
||||
import fixtures from '@pnpm/test-fixtures'
|
||||
import readYamlFile from 'read-yaml-file'
|
||||
import { addDependenciesToPackage, mutateModules } from '@pnpm/core'
|
||||
import { addDependenciesToPackage, mutateModulesInSingleProject } from '@pnpm/core'
|
||||
import rimraf from '@zkochan/rimraf'
|
||||
import { testDefaults } from '../utils'
|
||||
|
||||
@@ -45,18 +45,13 @@ test(`tarball location is correctly saved to ${WANTED_LOCKFILE} when a shared ${
|
||||
f.copy('tar-pkg-with-dep-2/tar-pkg-with-dep-1.0.0.tgz', 'pkg.tgz')
|
||||
|
||||
const lockfileDir = path.resolve('..')
|
||||
const [{ manifest }] = await mutateModules(
|
||||
[
|
||||
{
|
||||
allowNew: true,
|
||||
dependencySelectors: ['file:pkg.tgz'],
|
||||
manifest: {},
|
||||
mutation: 'installSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ lockfileDir })
|
||||
)
|
||||
const { manifest } = await mutateModulesInSingleProject({
|
||||
allowNew: true,
|
||||
dependencySelectors: ['file:pkg.tgz'],
|
||||
manifest: {},
|
||||
mutation: 'installSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ lockfileDir }))
|
||||
|
||||
const lockfile = await readYamlFile<Lockfile>(path.resolve('..', WANTED_LOCKFILE))
|
||||
expect(lockfile.packages!['file:project/pkg.tgz']).toBeTruthy()
|
||||
@@ -64,17 +59,11 @@ test(`tarball location is correctly saved to ${WANTED_LOCKFILE} when a shared ${
|
||||
|
||||
await rimraf('node_modules')
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ frozenLockfile: true, lockfileDir })
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true, lockfileDir }))
|
||||
|
||||
await project.has('tar-pkg-with-dep')
|
||||
})
|
||||
|
||||
@@ -16,7 +16,7 @@ import { addDistTag, getIntegrity, REGISTRY_MOCK_PORT } from '@pnpm/registry-moc
|
||||
import {
|
||||
addDependenciesToPackage,
|
||||
install,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
UnexpectedStoreError,
|
||||
UnexpectedVirtualStoreDirError,
|
||||
} from '@pnpm/core'
|
||||
@@ -912,14 +912,11 @@ test('do not update deps when lockfile is present', async () => {
|
||||
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-a', version: '1.0.1', distTag: 'latest' })
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ preferFrozenLockfile: false }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ preferFrozenLockfile: false }))
|
||||
|
||||
const latestLockfile = await project.readLockfile()
|
||||
|
||||
@@ -929,18 +926,15 @@ test('do not update deps when lockfile is present', async () => {
|
||||
test('all the subdeps of dependencies are linked when a node_modules is partially up to date', async () => {
|
||||
prepareEmpty()
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@pnpm.e2e/foobarqar': '1.0.0',
|
||||
},
|
||||
await mutateModulesInSingleProject({
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@pnpm.e2e/foobarqar': '1.0.0',
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults())
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults())
|
||||
|
||||
await writeYamlFile(path.resolve('pnpm-lock.yaml'), {
|
||||
dependencies: {
|
||||
@@ -986,18 +980,15 @@ test('all the subdeps of dependencies are linked when a node_modules is partiall
|
||||
},
|
||||
}, { lineWidth: 1000 })
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@pnpm.e2e/foobarqar': '1.0.1',
|
||||
},
|
||||
await mutateModulesInSingleProject({
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@pnpm.e2e/foobarqar': '1.0.1',
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ preferFrozenLockfile: false }))
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ preferFrozenLockfile: false }))
|
||||
|
||||
expect(
|
||||
[...await fs.readdir(path.resolve('node_modules/.pnpm/@pnpm.e2e+foobarqar@1.0.1/node_modules/@pnpm.e2e'))].sort()
|
||||
@@ -1015,18 +1006,15 @@ test('subdep symlinks are updated if the lockfile has new subdep versions specif
|
||||
await addDistTag({ package: '@pnpm.e2e/dep-of-pkg-with-1-dep', version: '100.0.0', distTag: 'latest' })
|
||||
const project = prepareEmpty()
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@pnpm.e2e/parent-of-pkg-with-1-dep': '1.0.0',
|
||||
},
|
||||
await mutateModulesInSingleProject({
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@pnpm.e2e/parent-of-pkg-with-1-dep': '1.0.0',
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults())
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults())
|
||||
|
||||
const lockfile = await project.readLockfile()
|
||||
|
||||
@@ -1076,18 +1064,15 @@ test('subdep symlinks are updated if the lockfile has new subdep versions specif
|
||||
},
|
||||
}, { lineWidth: 1000 })
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@pnpm.e2e/parent-of-pkg-with-1-dep': '1.0.0',
|
||||
},
|
||||
await mutateModulesInSingleProject({
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@pnpm.e2e/parent-of-pkg-with-1-dep': '1.0.0',
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ preferFrozenLockfile: false }))
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ preferFrozenLockfile: false }))
|
||||
|
||||
expect(await exists(path.resolve('node_modules/.pnpm/@pnpm.e2e+pkg-with-1-dep@100.0.0/node_modules/@pnpm.e2e/dep-of-pkg-with-1-dep/package.json'))).toBeTruthy()
|
||||
})
|
||||
@@ -1097,18 +1082,15 @@ test('fail if none of the available resolvers support a version spec', async ()
|
||||
|
||||
let err!: PnpmError
|
||||
try {
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@types/plotly.js': '1.44.29',
|
||||
},
|
||||
await mutateModulesInSingleProject({
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@types/plotly.js': '1.44.29',
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults())
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults())
|
||||
throw new Error('should have failed')
|
||||
} catch (_err: any) { // eslint-disable-line
|
||||
err = _err
|
||||
@@ -1132,18 +1114,15 @@ test('globally installed package which don\'t have bins should log warning messa
|
||||
|
||||
const opts = await testDefaults({ global: true, reporter })
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'is-positive': '1.0.0',
|
||||
},
|
||||
await mutateModulesInSingleProject({
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'is-positive': '1.0.0',
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], opts)
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, opts)
|
||||
|
||||
expect(reporter.calledWithMatch({
|
||||
message: 'is-positive has no binaries',
|
||||
@@ -1269,19 +1248,16 @@ test('installing dependencies with the same name in different case', async () =>
|
||||
},
|
||||
])
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
mutation: 'install',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
File: 'https://registry.npmjs.org/File/-/File-0.10.2.tgz',
|
||||
file: 'https://registry.npmjs.org/file/-/file-0.2.2.tgz',
|
||||
},
|
||||
await mutateModulesInSingleProject({
|
||||
mutation: 'install',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
File: 'https://registry.npmjs.org/File/-/File-0.10.2.tgz',
|
||||
file: 'https://registry.npmjs.org/file/-/file-0.2.2.tgz',
|
||||
},
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
], await testDefaults({ fastUnpack: false }))
|
||||
rootDir: path.resolve('project-1'),
|
||||
}, await testDefaults({ fastUnpack: false }))
|
||||
|
||||
// if it did not fail, it is fine
|
||||
})
|
||||
@@ -1289,19 +1265,16 @@ test('installing dependencies with the same name in different case', async () =>
|
||||
test('two dependencies have the same version and name. The only difference is the casing in the name', async () => {
|
||||
prepareEmpty()
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
mutation: 'install',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
a: 'npm:JSONStream@1.0.3',
|
||||
b: 'npm:jsonstream@1.0.3',
|
||||
},
|
||||
await mutateModulesInSingleProject({
|
||||
mutation: 'install',
|
||||
manifest: {
|
||||
dependencies: {
|
||||
a: 'npm:JSONStream@1.0.3',
|
||||
b: 'npm:jsonstream@1.0.3',
|
||||
},
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({
|
||||
fastUnpack: false,
|
||||
registries: {
|
||||
default: 'https://registry.npmjs.org/',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { prepareEmpty } from '@pnpm/prepare'
|
||||
import {
|
||||
addDependenciesToPackage,
|
||||
install,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import { testDefaults } from '../utils'
|
||||
|
||||
@@ -22,14 +22,12 @@ test('the modules cache is pruned when it expires', async () => {
|
||||
|
||||
expect(modulesFile?.prunedAt).toBeTruthy()
|
||||
|
||||
manifest = (await mutateModules([
|
||||
{
|
||||
dependencyNames: ['is-negative'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({})))[0].manifest
|
||||
manifest = (await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-negative'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({}))).manifest
|
||||
|
||||
await project.has('.pnpm/is-negative@1.0.0/node_modules/is-negative')
|
||||
|
||||
@@ -60,14 +58,12 @@ test('the modules cache is pruned when it expires and headless install is used',
|
||||
|
||||
expect(modulesFile?.prunedAt).toBeTruthy()
|
||||
|
||||
manifest = (await mutateModules([
|
||||
{
|
||||
dependencyNames: ['is-negative'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ lockfileOnly: true })))[0].manifest
|
||||
manifest = (await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-negative'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ lockfileOnly: true }))).manifest
|
||||
|
||||
manifest = await install(manifest, await testDefaults({ frozenLockfile: true }))
|
||||
|
||||
|
||||
@@ -52,6 +52,16 @@ test('using different custom modules directory for every project', async () => {
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
@@ -63,7 +73,6 @@ test('using different custom modules directory for every project', async () => {
|
||||
},
|
||||
},
|
||||
modulesDir: 'modules_1',
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
@@ -77,11 +86,10 @@ test('using different custom modules directory for every project', async () => {
|
||||
},
|
||||
},
|
||||
modulesDir: 'modules_2',
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
await mutateModules(importers, await testDefaults())
|
||||
await mutateModules(importers, await testDefaults({ allProjects }))
|
||||
|
||||
await projects['project-1'].has('is-positive', 'modules_1')
|
||||
await projects['project-2'].has('is-positive', 'modules_2')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@ import {
|
||||
install,
|
||||
MutatedProject,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import rimraf from '@zkochan/rimraf'
|
||||
import exists from 'path-exists'
|
||||
@@ -115,17 +116,11 @@ test('skip optional dependency that does not support the current OS', async () =
|
||||
|
||||
await rimraf('node_modules')
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ frozenLockfile: true })
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true }))
|
||||
|
||||
await project.hasNot('@pnpm.e2e/not-compatible-with-any-os')
|
||||
await project.has('@pnpm.e2e/dep-of-optional-pkg')
|
||||
@@ -217,6 +212,16 @@ test('optional subdependency is not removed from current lockfile when new depen
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
@@ -227,7 +232,6 @@ test('optional subdependency is not removed from current lockfile when new depen
|
||||
'@pnpm.e2e/pkg-with-optional': '1.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
@@ -236,12 +240,11 @@ test('optional subdependency is not removed from current lockfile when new depen
|
||||
name: 'project-2',
|
||||
version: '1.0.0',
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
await mutateModules(importers,
|
||||
await testDefaults({ hoistPattern: ['*'] })
|
||||
await testDefaults({ allProjects, hoistPattern: ['*'] })
|
||||
)
|
||||
|
||||
{
|
||||
@@ -258,7 +261,7 @@ test('optional subdependency is not removed from current lockfile when new depen
|
||||
dependencySelectors: ['is-positive@1.0.0'],
|
||||
mutation: 'installSome',
|
||||
},
|
||||
], await testDefaults({ fastUnpack: false, hoistPattern: ['*'] }))
|
||||
], await testDefaults({ allProjects, fastUnpack: false, hoistPattern: ['*'] }))
|
||||
|
||||
{
|
||||
const currentLockfile = await readYamlFile<Lockfile>(path.resolve('node_modules/.pnpm/lock.yaml'))
|
||||
@@ -296,16 +299,11 @@ test('optional subdependency is skipped', async () => {
|
||||
expect(await exists('pnpm-lock.yaml')).toBeTruthy()
|
||||
await rimraf('pnpm-lock.yaml')
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults()
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults()
|
||||
)
|
||||
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -316,17 +314,11 @@ test('optional subdependency is skipped', async () => {
|
||||
// forced headless install should install non-compatible optional deps
|
||||
|
||||
// TODO: move next case to @pnpm/headless tests
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ force: true, frozenLockfile: true })
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ force: true, frozenLockfile: true }))
|
||||
|
||||
expect(await exists('node_modules/.pnpm/@pnpm.e2e+not-compatible-with-any-os@1.0.0')).toBeTruthy()
|
||||
|
||||
@@ -372,19 +364,11 @@ test('only that package is skipped which is an optional dependency only and not
|
||||
|
||||
await rimraf('node_modules')
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({
|
||||
frozenLockfile: true,
|
||||
})
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true }))
|
||||
|
||||
{
|
||||
const modulesInfo = await readYamlFile<{ skipped: string[] }>(path.join('node_modules', '.modules.yaml'))
|
||||
@@ -484,53 +468,55 @@ test('skip optional dependency that does not support the current OS, when doing
|
||||
const [{ manifest }] = await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project1',
|
||||
version: '1.0.0',
|
||||
|
||||
optionalDependencies: {
|
||||
'@pnpm.e2e/not-compatible-with-any-os': '*',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project2',
|
||||
version: '1.0.0',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/pkg-with-1-dep': '100.0.0',
|
||||
},
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project2'),
|
||||
},
|
||||
],
|
||||
await testDefaults({
|
||||
allProjects: [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project1',
|
||||
version: '1.0.0',
|
||||
|
||||
optionalDependencies: {
|
||||
'@pnpm.e2e/not-compatible-with-any-os': '*',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
name: 'project2',
|
||||
version: '1.0.0',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/pkg-with-1-dep': '100.0.0',
|
||||
},
|
||||
},
|
||||
rootDir: path.resolve('project2'),
|
||||
},
|
||||
],
|
||||
lockfileDir: process.cwd(),
|
||||
lockfileOnly: true,
|
||||
})
|
||||
)
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project1'),
|
||||
},
|
||||
],
|
||||
await testDefaults({
|
||||
frozenLockfile: false,
|
||||
lockfileDir: process.cwd(),
|
||||
preferFrozenLockfile: false,
|
||||
})
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project1'),
|
||||
}, await testDefaults({
|
||||
frozenLockfile: false,
|
||||
lockfileDir: process.cwd(),
|
||||
preferFrozenLockfile: false,
|
||||
}))
|
||||
|
||||
const modulesInfo = await readYamlFile<{ skipped: string[] }>(path.join('node_modules', '.modules.yaml'))
|
||||
expect(modulesInfo.skipped).toStrictEqual([
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import PnpmError from '@pnpm/error'
|
||||
import { prepareEmpty } from '@pnpm/prepare'
|
||||
import { addDistTag } from '@pnpm/registry-mock'
|
||||
import { addDependenciesToPackage, mutateModules } from '@pnpm/core'
|
||||
import { addDependenciesToPackage, mutateModulesInSingleProject } from '@pnpm/core'
|
||||
import {
|
||||
testDefaults,
|
||||
} from '../utils'
|
||||
@@ -37,27 +37,21 @@ test('versions are replaced with versions specified through overrides option', a
|
||||
expect(lockfile.overrides).toStrictEqual(currentLockfile.overrides)
|
||||
}
|
||||
// shall be able to install when package manifest is ignored
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], { ...await testDefaults(), ignorePackageManifest: true, overrides })
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, { ...await testDefaults(), ignorePackageManifest: true, overrides })
|
||||
|
||||
// The lockfile is updated if the overrides are changed
|
||||
overrides['@pnpm.e2e/bar@^100.0.0'] = '100.0.0'
|
||||
// A direct dependency may be overriden as well
|
||||
overrides['@pnpm.e2e/foobarqar'] = '1.0.1'
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ overrides }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ overrides }))
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -74,14 +68,11 @@ test('versions are replaced with versions specified through overrides option', a
|
||||
expect(lockfile.overrides).toStrictEqual(currentLockfile.overrides)
|
||||
}
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ frozenLockfile: true, overrides }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true, overrides }))
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -97,14 +88,11 @@ test('versions are replaced with versions specified through overrides option', a
|
||||
|
||||
overrides['@pnpm.e2e/bar@^100.0.0'] = '100.0.1'
|
||||
await expect(
|
||||
mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ frozenLockfile: true, overrides }))
|
||||
mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true, overrides }))
|
||||
).rejects.toThrow(
|
||||
new PnpmError('FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE',
|
||||
'Cannot perform a frozen installation because the lockfile needs updates'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import PnpmError from '@pnpm/error'
|
||||
import { prepareEmpty } from '@pnpm/prepare'
|
||||
import { addDependenciesToPackage, mutateModules } from '@pnpm/core'
|
||||
import { addDependenciesToPackage, mutateModulesInSingleProject } from '@pnpm/core'
|
||||
import { createObjectChecksum } from '../../lib/install/index'
|
||||
import {
|
||||
testDefaults,
|
||||
@@ -38,14 +38,11 @@ test('manifests are extended with fields specified by packageExtensions', async
|
||||
|
||||
// The lockfile is updated if the overrides are changed
|
||||
packageExtensions['is-positive'].dependencies!['@pnpm.e2e/foobar'] = '100.0.0'
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ packageExtensions }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ packageExtensions }))
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -62,14 +59,11 @@ test('manifests are extended with fields specified by packageExtensions', async
|
||||
expect(lockfile.packageExtensionsChecksum).toStrictEqual(currentLockfile.packageExtensionsChecksum)
|
||||
}
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ frozenLockfile: true, packageExtensions }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true, packageExtensions }))
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -87,14 +81,11 @@ test('manifests are extended with fields specified by packageExtensions', async
|
||||
|
||||
packageExtensions['is-positive'].dependencies!['@pnpm.e2e/bar'] = '100.0.1'
|
||||
await expect(
|
||||
mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ frozenLockfile: true, packageExtensions }))
|
||||
mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true, packageExtensions }))
|
||||
).rejects.toThrow(
|
||||
new PnpmError('FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE',
|
||||
'Cannot perform a frozen installation because the lockfile needs updates'
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
install,
|
||||
MutatedProject,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
PeerDependencyIssuesError,
|
||||
} from '@pnpm/core'
|
||||
import rimraf from '@zkochan/rimraf'
|
||||
@@ -65,14 +66,12 @@ test('nothing is needlessly removed from node_modules', async () => {
|
||||
expect(await exists(path.resolve('node_modules/.pnpm/ajv-keywords@1.5.0/node_modules/ajv-keywords'))).toBeTruthy()
|
||||
expect(deepRequireCwd(['@pnpm.e2e/using-ajv', 'ajv-keywords', 'ajv', './package.json']).version).toBe('4.10.4')
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: ['ajv-keywords'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], opts)
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['ajv-keywords'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, opts)
|
||||
|
||||
expect(await exists(path.resolve('node_modules/.pnpm/ajv-keywords@1.5.0_ajv@4.10.4/node_modules/ajv'))).toBeTruthy()
|
||||
expect(await exists(path.resolve('node_modules/.pnpm/ajv-keywords@1.5.0/node_modules/ajv-keywords'))).toBeFalsy()
|
||||
@@ -91,14 +90,11 @@ test('peer dependency is grouped with dependent when the peer is a top dependenc
|
||||
|
||||
expect(await exists(path.resolve('node_modules/.pnpm/ajv-keywords@1.5.0_ajv@4.10.4/node_modules/ajv-keywords'))).toBeTruthy()
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ preferFrozenLockfile: false }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ preferFrozenLockfile: false }))
|
||||
|
||||
const lockfile = await project.readLockfile()
|
||||
expect(lockfile.packages['/ajv-keywords/1.5.0_ajv@4.10.4'].dependencies).toHaveProperty(['ajv'])
|
||||
@@ -132,20 +128,28 @@ test('the right peer dependency is used in every workspace package', async () =>
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: manifest1,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: manifest2,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
await mutateModules(importers, await testDefaults({ lockfileOnly: true, strictPeerDependencies: false }))
|
||||
await mutateModules(importers, await testDefaults({ allProjects, lockfileOnly: true, strictPeerDependencies: false }))
|
||||
|
||||
const lockfile = await readYamlFile<Lockfile>(path.resolve(WANTED_LOCKFILE))
|
||||
|
||||
@@ -403,14 +407,11 @@ test('the list of transitive peer dependencies is kept up to date', async () =>
|
||||
expect(lockfile.packages['/@pnpm.e2e/abc-grand-parent/1.0.0_@pnpm.e2e+peer-c@1.0.0'].transitivePeerDependencies).toStrictEqual(['@pnpm.e2e/peer-c'])
|
||||
}
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ update: true, depth: Infinity }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ update: true, depth: Infinity }))
|
||||
|
||||
expect(await exists(path.resolve('node_modules/.pnpm/@pnpm.e2e+abc-grand-parent@1.0.0/node_modules/@pnpm.e2e/abc-grand-parent'))).toBeTruthy()
|
||||
|
||||
@@ -669,19 +670,15 @@ test('peer dependency is grouped with dependent when the peer is a top dependenc
|
||||
}
|
||||
|
||||
// Covers https://github.com/pnpm/pnpm/issues/1506
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
dependencyNames: ['ajv'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({
|
||||
lockfileDir,
|
||||
strictPeerDependencies: false,
|
||||
})
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['ajv'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({
|
||||
lockfileDir,
|
||||
strictPeerDependencies: false,
|
||||
})
|
||||
)
|
||||
|
||||
{
|
||||
@@ -799,14 +796,12 @@ test('peer dependency is resolved from parent package', async () => {
|
||||
name: 'pkg',
|
||||
},
|
||||
])
|
||||
await mutateModules([
|
||||
{
|
||||
dependencySelectors: ['@pnpm.e2e/tango@1.0.0'],
|
||||
manifest: {},
|
||||
mutation: 'installSome',
|
||||
rootDir: path.resolve('pkg'),
|
||||
},
|
||||
], await testDefaults())
|
||||
await mutateModulesInSingleProject({
|
||||
dependencySelectors: ['@pnpm.e2e/tango@1.0.0'],
|
||||
manifest: {},
|
||||
mutation: 'installSome',
|
||||
rootDir: path.resolve('pkg'),
|
||||
}, await testDefaults())
|
||||
|
||||
const lockfile = await readYamlFile<Lockfile>(WANTED_LOCKFILE)
|
||||
expect(Object.keys(lockfile.packages ?? {})).toStrictEqual([
|
||||
@@ -821,23 +816,19 @@ test('transitive peerDependencies field does not break the lockfile on subsequen
|
||||
name: 'pkg',
|
||||
},
|
||||
])
|
||||
const [{ manifest }] = await mutateModules([
|
||||
{
|
||||
dependencySelectors: ['most@1.7.3'],
|
||||
manifest: {},
|
||||
mutation: 'installSome',
|
||||
rootDir: path.resolve('pkg'),
|
||||
},
|
||||
], await testDefaults())
|
||||
const { manifest } = await mutateModulesInSingleProject({
|
||||
dependencySelectors: ['most@1.7.3'],
|
||||
manifest: {},
|
||||
mutation: 'installSome',
|
||||
rootDir: path.resolve('pkg'),
|
||||
}, await testDefaults())
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
dependencySelectors: ['is-positive'],
|
||||
manifest,
|
||||
mutation: 'installSome',
|
||||
rootDir: path.resolve('pkg'),
|
||||
},
|
||||
], await testDefaults())
|
||||
await mutateModulesInSingleProject({
|
||||
dependencySelectors: ['is-positive'],
|
||||
manifest,
|
||||
mutation: 'installSome',
|
||||
rootDir: path.resolve('pkg'),
|
||||
}, await testDefaults())
|
||||
|
||||
const lockfile = await readYamlFile<Lockfile>(WANTED_LOCKFILE)
|
||||
|
||||
@@ -854,14 +845,12 @@ test('peer dependency is resolved from parent package via its alias', async () =
|
||||
name: 'pkg',
|
||||
},
|
||||
])
|
||||
await mutateModules([
|
||||
{
|
||||
dependencySelectors: ['@pnpm.e2e/tango@npm:@pnpm.e2e/tango-tango@1.0.0'],
|
||||
manifest: {},
|
||||
mutation: 'installSome',
|
||||
rootDir: path.resolve('pkg'),
|
||||
},
|
||||
], await testDefaults())
|
||||
await mutateModulesInSingleProject({
|
||||
dependencySelectors: ['@pnpm.e2e/tango@npm:@pnpm.e2e/tango-tango@1.0.0'],
|
||||
manifest: {},
|
||||
mutation: 'installSome',
|
||||
rootDir: path.resolve('pkg'),
|
||||
}, await testDefaults())
|
||||
|
||||
const lockfile = await readYamlFile<Lockfile>(WANTED_LOCKFILE)
|
||||
const suffix = createPeersFolderSuffix([{ name: '@pnpm.e2e/tango-tango', version: '1.0.0' }])
|
||||
@@ -890,14 +879,12 @@ test('peer dependency is saved', async () => {
|
||||
}
|
||||
)
|
||||
|
||||
const [mutatedImporter] = await mutateModules([
|
||||
{
|
||||
dependencyNames: ['is-positive'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults())
|
||||
const mutatedImporter = await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-positive'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults())
|
||||
|
||||
expect(mutatedImporter.manifest).toStrictEqual(
|
||||
{
|
||||
@@ -1061,14 +1048,11 @@ test('local tarball dependency with peer dependency', async () => {
|
||||
|
||||
await rimraf('node_modules')
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults())
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults())
|
||||
|
||||
{
|
||||
const updatedLocalPkgDirs = (await fs.readdir('node_modules/.pnpm'))
|
||||
@@ -1088,26 +1072,20 @@ test('peer dependency that is resolved by a dev dependency', async () => {
|
||||
},
|
||||
}
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ fastUnpack: false, lockfileOnly: true, strictPeerDependencies: false }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ fastUnpack: false, lockfileOnly: true, strictPeerDependencies: false }))
|
||||
|
||||
const lockfile = await project.readLockfile()
|
||||
expect(lockfile.packages['/@types/mongoose/5.7.32'].dev).toBeUndefined()
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({
|
||||
frozenLockfile: true,
|
||||
include: {
|
||||
dependencies: true,
|
||||
@@ -1144,20 +1122,28 @@ test('peer dependency is grouped with dependency when peer is resolved not from
|
||||
},
|
||||
])
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('ajv'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project1Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: project2Manifest,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('ajv'),
|
||||
},
|
||||
]
|
||||
await mutateModules(importers, await testDefaults({}))
|
||||
await mutateModules(importers, await testDefaults({ allProjects }))
|
||||
|
||||
const lockfile = await readYamlFile<Lockfile>(path.resolve(WANTED_LOCKFILE))
|
||||
expect(lockfile.packages?.['/ajv-keywords/1.5.0_ajv@ajv'].dependencies?.['ajv']).toBe('link:ajv')
|
||||
|
||||
@@ -2,7 +2,7 @@ import { prepareEmpty } from '@pnpm/prepare'
|
||||
import {
|
||||
addDependenciesToPackage,
|
||||
install,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import { addDistTag } from '@pnpm/registry-mock'
|
||||
import { testDefaults } from '../utils'
|
||||
@@ -197,24 +197,21 @@ test('an update bumps the versions in the manifest', async () => {
|
||||
|
||||
prepareEmpty()
|
||||
|
||||
const [{ manifest }] = await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@pnpm.e2e/peer-a': '~1.0.0',
|
||||
},
|
||||
devDependencies: {
|
||||
'@pnpm.e2e/foo': '^100.0.0',
|
||||
},
|
||||
optionalDependencies: {
|
||||
'@pnpm.e2e/peer-c': '^1.0.1',
|
||||
},
|
||||
const { manifest } = await mutateModulesInSingleProject({
|
||||
manifest: {
|
||||
dependencies: {
|
||||
'@pnpm.e2e/peer-a': '~1.0.0',
|
||||
},
|
||||
devDependencies: {
|
||||
'@pnpm.e2e/foo': '^100.0.0',
|
||||
},
|
||||
optionalDependencies: {
|
||||
'@pnpm.e2e/peer-c': '^1.0.1',
|
||||
},
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
await testDefaults({
|
||||
update: true,
|
||||
}))
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
addDependenciesToPackage,
|
||||
install,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import rimraf from '@zkochan/rimraf'
|
||||
import loadJsonFile from 'load-json-file'
|
||||
@@ -692,14 +693,12 @@ test(`don't update ${WANTED_LOCKFILE} during uninstall when useLockfile: false`,
|
||||
{
|
||||
const reporter = sinon.spy()
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: ['is-positive'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ useLockfile: false, reporter }))
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-positive'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ useLockfile: false, reporter }))
|
||||
|
||||
expect(reporter.calledWithMatch(LOCKFILE_WARN_LOG)).toBeTruthy()
|
||||
}
|
||||
@@ -943,19 +942,28 @@ test(`doing named installation when shared ${WANTED_LOCKFILE} exists already`, a
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: pkg1,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('pkg1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: pkg2,
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('pkg2'),
|
||||
},
|
||||
],
|
||||
await testDefaults()
|
||||
await testDefaults({
|
||||
allProjects: [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: pkg1,
|
||||
rootDir: path.resolve('pkg1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: pkg2,
|
||||
rootDir: path.resolve('pkg2'),
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
|
||||
await projects['pkg1'].has('is-negative')
|
||||
@@ -989,14 +997,11 @@ test('existing dependencies are preserved when updating a lockfile to a newer fo
|
||||
|
||||
await addDistTag({ package: '@pnpm.e2e/dep-of-pkg-with-1-dep', version: '100.1.0', distTag: 'latest' })
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults())
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults())
|
||||
|
||||
const updatedLockfile = await project.readLockfile()
|
||||
|
||||
@@ -1017,14 +1022,11 @@ test('lockfile is not getting broken if the used registry changes', async () =>
|
||||
}
|
||||
expect(err.code).toBe('ERR_PNPM_REGISTRIES_MISMATCH')
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], newOpts)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, newOpts)
|
||||
await addDependenciesToPackage(manifest, ['is-negative@1'], newOpts)
|
||||
|
||||
expect(Object.keys((await project.readLockfile()).packages)).toStrictEqual([
|
||||
@@ -1047,27 +1049,21 @@ test('broken lockfile is fixed even if it seems like up to date at first. Unless
|
||||
|
||||
let err!: PnpmError
|
||||
try {
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ frozenLockfile: true }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ frozenLockfile: true }))
|
||||
} catch (_err: any) { // eslint-disable-line
|
||||
err = _err
|
||||
}
|
||||
expect(err.code).toBe('ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY')
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ preferFrozenLockfile: true }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ preferFrozenLockfile: true }))
|
||||
|
||||
await project.has('@pnpm.e2e/pkg-with-1-dep')
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -1300,14 +1296,11 @@ packages:
|
||||
|
||||
const reporter = jest.fn()
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
mutation: 'install',
|
||||
manifest,
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ reporter }))
|
||||
await mutateModulesInSingleProject({
|
||||
mutation: 'install',
|
||||
manifest,
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ reporter }))
|
||||
|
||||
expect(reporter).toBeCalledWith(expect.objectContaining({
|
||||
level: 'warn',
|
||||
@@ -1352,14 +1345,11 @@ test('a broken lockfile should not break the store', async () => {
|
||||
|
||||
await writeYamlFile(WANTED_LOCKFILE, lockfile)
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ lockfileOnly: true, storeDir: path.resolve('store2') }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ lockfileOnly: true, storeDir: path.resolve('store2') }))
|
||||
|
||||
delete lockfile.packages!['/is-positive/1.0.0'].name
|
||||
delete lockfile.packages!['/is-positive/1.0.0'].version
|
||||
@@ -1367,14 +1357,11 @@ test('a broken lockfile should not break the store', async () => {
|
||||
await writeYamlFile(WANTED_LOCKFILE, lockfile)
|
||||
await rimraf(path.resolve('node_modules'))
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ lockfileOnly: true, storeDir: path.resolve('store2') }))
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ lockfileOnly: true, storeDir: path.resolve('store2') }))
|
||||
})
|
||||
|
||||
test('include tarball URL', async () => {
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
addDependenciesToPackage,
|
||||
install,
|
||||
link,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import sinon from 'sinon'
|
||||
import { testDefaults } from './utils'
|
||||
@@ -31,22 +31,16 @@ test('prune removes extraneous packages', async () => {
|
||||
|
||||
const reporter = sinon.spy()
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
pruneDirectDependencies: true,
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
{
|
||||
...opts,
|
||||
pruneStore: true,
|
||||
reporter,
|
||||
}
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
pruneDirectDependencies: true,
|
||||
rootDir: process.cwd(),
|
||||
}, {
|
||||
...opts,
|
||||
pruneStore: true,
|
||||
reporter,
|
||||
})
|
||||
|
||||
expect(reporter.calledWithMatch({
|
||||
level: 'debug',
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
addDependenciesToPackage,
|
||||
link,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import exists from 'path-exists'
|
||||
import sinon from 'sinon'
|
||||
@@ -30,14 +31,12 @@ test('uninstall package with no dependencies', async () => {
|
||||
let manifest = await addDependenciesToPackage({}, ['is-negative@2.1.0'], await testDefaults({ save: true }))
|
||||
|
||||
const reporter = sinon.spy()
|
||||
manifest = (await mutateModules([
|
||||
{
|
||||
dependencyNames: ['is-negative'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ save: true, reporter })))[0].manifest
|
||||
manifest = (await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-negative'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ save: true, reporter }))).manifest
|
||||
|
||||
expect(reporter.calledWithMatch({
|
||||
initial: {
|
||||
@@ -85,14 +84,12 @@ test('uninstall a dependency that is not present in node_modules', async () => {
|
||||
prepareEmpty()
|
||||
|
||||
const reporter = sinon.spy()
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: ['is-negative'],
|
||||
manifest: {},
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ reporter }))
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-negative'],
|
||||
manifest: {},
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ reporter }))
|
||||
|
||||
expect(reporter.calledWithMatch({
|
||||
level: 'debug',
|
||||
@@ -106,14 +103,12 @@ test('uninstall a dependency that is not present in node_modules', async () => {
|
||||
test('uninstall scoped package', async () => {
|
||||
const project = prepareEmpty()
|
||||
let manifest = await addDependenciesToPackage({}, ['@zkochan/logger@0.1.0'], await testDefaults({ save: true }))
|
||||
manifest = (await mutateModules([
|
||||
{
|
||||
dependencyNames: ['@zkochan/logger'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ save: true })))[0].manifest
|
||||
manifest = (await mutateModulesInSingleProject({
|
||||
dependencyNames: ['@zkochan/logger'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ save: true }))).manifest
|
||||
|
||||
await project.storeHas('@zkochan/logger', '0.1.0')
|
||||
|
||||
@@ -127,14 +122,12 @@ test('uninstall tarball dependency', async () => {
|
||||
const opts = await testDefaults({ save: true })
|
||||
|
||||
let manifest = await addDependenciesToPackage({}, [`http://localhost:${REGISTRY_MOCK_PORT}/is-array/-/is-array-1.0.1.tgz`], opts)
|
||||
manifest = (await mutateModules([
|
||||
{
|
||||
dependencyNames: ['is-array'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], opts))[0].manifest
|
||||
manifest = (await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-array'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, opts)).manifest
|
||||
|
||||
await project.storeHas('is-array', '1.0.1')
|
||||
await project.hasNot('is-array')
|
||||
@@ -145,14 +138,12 @@ test('uninstall tarball dependency', async () => {
|
||||
test('uninstall package with dependencies and do not touch other deps', async () => {
|
||||
const project = prepareEmpty()
|
||||
let manifest = await addDependenciesToPackage({}, ['is-negative@2.1.0', 'camelcase-keys@3.0.0'], await testDefaults({ save: true }))
|
||||
manifest = (await mutateModules([
|
||||
{
|
||||
dependencyNames: ['camelcase-keys'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ pruneStore: true, save: true })))[0].manifest
|
||||
manifest = (await mutateModulesInSingleProject({
|
||||
dependencyNames: ['camelcase-keys'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ pruneStore: true, save: true }))).manifest
|
||||
|
||||
await project.storeHasNot('camelcase-keys', '3.0.0')
|
||||
await project.hasNot('camelcase-keys')
|
||||
@@ -180,14 +171,12 @@ test('uninstall package with dependencies and do not touch other deps', async ()
|
||||
test('uninstall package with its bin files', async () => {
|
||||
prepareEmpty()
|
||||
const manifest = await addDependenciesToPackage({}, ['@pnpm.e2e/sh-hello-world@1.0.1'], await testDefaults({ fastUnpack: false, save: true }))
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: ['@pnpm.e2e/sh-hello-world'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ save: true }))
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['@pnpm.e2e/sh-hello-world'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ save: true }))
|
||||
|
||||
// check for both a symlink and a file because in some cases the file will be a proxied not symlinked
|
||||
const stat = await existsSymlink(path.resolve('node_modules', '.bin', 'sh-hello-world'))
|
||||
@@ -207,14 +196,12 @@ test('relative link is uninstalled', async () => {
|
||||
|
||||
f.copy(linkedPkgName, linkedPkgPath)
|
||||
const manifest = await link([`../${linkedPkgName}`], path.join(process.cwd(), 'node_modules'), opts as (typeof opts & { dir: string, manifest: PackageManifest }))
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: [linkedPkgName],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], opts)
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: [linkedPkgName],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, opts)
|
||||
|
||||
await project.hasNot(linkedPkgName)
|
||||
})
|
||||
@@ -231,14 +218,12 @@ test('pendingBuilds gets updated after uninstall', async () => {
|
||||
expect(modules1).toBeTruthy()
|
||||
expect(modules1!.pendingBuilds.length).toBe(2)
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: ['@pnpm.e2e/with-postinstall-b'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ save: true }))
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['@pnpm.e2e/with-postinstall-b'],
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ save: true }))
|
||||
|
||||
const modules2 = await project.readModulesManifest()
|
||||
expect(modules2).toBeTruthy()
|
||||
@@ -272,19 +257,27 @@ test('uninstalling a dependency from package that uses shared lockfile', async (
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: pkgs[0],
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: pkgs[1],
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
],
|
||||
await testDefaults({
|
||||
allProjects: [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: pkgs[0],
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: pkgs[1],
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
],
|
||||
store,
|
||||
workspacePackages: {
|
||||
'project-2': {
|
||||
@@ -307,14 +300,12 @@ test('uninstalling a dependency from package that uses shared lockfile', async (
|
||||
await projects['project-1'].has('is-positive')
|
||||
await projects['project-2'].has('is-negative')
|
||||
|
||||
await mutateModules([
|
||||
{
|
||||
dependencyNames: ['is-positive', 'project-2'],
|
||||
manifest: pkgs[0],
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
], await testDefaults({
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-positive', 'project-2'],
|
||||
manifest: pkgs[0],
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: path.resolve('project-1'),
|
||||
}, await testDefaults({
|
||||
lockfileDir: process.cwd(),
|
||||
store,
|
||||
pruneLockfileImporters: false,
|
||||
@@ -361,17 +352,12 @@ test('uninstall remove modules that is not in package.json', async () => {
|
||||
|
||||
await project.has('foo')
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
dependencyNames: ['foo'],
|
||||
manifest: {},
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults()
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['foo'],
|
||||
manifest: {},
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults())
|
||||
|
||||
await project.hasNot('foo')
|
||||
})
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
addDependenciesToPackage,
|
||||
install,
|
||||
link,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
} from '@pnpm/core'
|
||||
import { prepareEmpty } from '@pnpm/prepare'
|
||||
import { WANTED_LOCKFILE } from '@pnpm/constants'
|
||||
@@ -54,17 +54,12 @@ test('unlink 1 package that exists in package.json', async () => {
|
||||
|
||||
manifest = await install(manifest, opts)
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
dependencyNames: ['is-subdir'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
opts
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-subdir'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
}, opts)
|
||||
|
||||
expect(typeof project.requireModule('is-subdir')).toBe('function')
|
||||
expect((await isInnerLink('node_modules', 'is-positive')).isInner).toBeFalsy()
|
||||
@@ -88,17 +83,12 @@ test("don't update package when unlinking", async () => {
|
||||
await addDistTag({ package: '@pnpm.e2e/foo', version: '100.1.0', distTag: 'latest' })
|
||||
|
||||
process.chdir('project')
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
dependencyNames: ['@pnpm.e2e/foo'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
opts
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['@pnpm.e2e/foo'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
}, opts)
|
||||
|
||||
expect(project.requireModule('@pnpm.e2e/foo/package.json').version).toBe('100.0.0')
|
||||
})
|
||||
@@ -125,20 +115,15 @@ test(`don't update package when unlinking. Initial link is done on a package w/o
|
||||
await addDistTag({ package: '@pnpm.e2e/foo', version: '100.1.0', distTag: 'latest' })
|
||||
|
||||
process.chdir('project')
|
||||
const unlinkResult = await mutateModules(
|
||||
[
|
||||
{
|
||||
dependencyNames: ['@pnpm.e2e/foo'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
opts
|
||||
)
|
||||
const unlinkResult = await mutateModulesInSingleProject({
|
||||
dependencyNames: ['@pnpm.e2e/foo'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
}, opts)
|
||||
|
||||
expect(project.requireModule('@pnpm.e2e/foo/package.json').version).toBe('100.1.0')
|
||||
expect(unlinkResult[0].manifest.dependencies).toStrictEqual({ '@pnpm.e2e/foo': '^100.0.0' })
|
||||
expect(unlinkResult.manifest.dependencies).toStrictEqual({ '@pnpm.e2e/foo': '^100.0.0' })
|
||||
})
|
||||
|
||||
test('unlink 2 packages. One of them exists in package.json', async () => {
|
||||
@@ -170,17 +155,12 @@ test('unlink 2 packages. One of them exists in package.json', async () => {
|
||||
})
|
||||
|
||||
process.chdir('project')
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
dependencyNames: ['is-subdir', 'is-positive'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
opts
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-subdir', 'is-positive'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
}, opts)
|
||||
|
||||
expect(typeof project.requireModule('is-subdir')).toBe('function')
|
||||
expect(await exists(path.join('node_modules', 'is-positive'))).toBeFalsy()
|
||||
@@ -215,16 +195,11 @@ test('unlink all packages', async () => {
|
||||
},
|
||||
})
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
manifest,
|
||||
mutation: 'unlink',
|
||||
rootDir: path.resolve('project'),
|
||||
},
|
||||
],
|
||||
opts
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'unlink',
|
||||
rootDir: path.resolve('project'),
|
||||
}, opts)
|
||||
|
||||
expect(typeof project.requireModule('is-subdir')).toBe('function')
|
||||
expect(typeof project.requireModule('@zkochan/logger')).toBe('object')
|
||||
@@ -236,16 +211,11 @@ test("don't warn about scoped packages when running unlink w/o params", async ()
|
||||
const manifest = await addDependenciesToPackage({}, ['@zkochan/logger'], await testDefaults())
|
||||
|
||||
const reporter = sinon.spy()
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
manifest,
|
||||
mutation: 'unlink',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ reporter })
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
manifest,
|
||||
mutation: 'unlink',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ reporter }))
|
||||
|
||||
expect(reporter.calledWithMatch({
|
||||
level: 'warn',
|
||||
@@ -260,17 +230,12 @@ test("don't unlink package that is not a link", async () => {
|
||||
|
||||
const manifest = await addDependenciesToPackage({}, ['is-positive'], await testDefaults())
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
dependencyNames: ['is-positive'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
await testDefaults({ reporter })
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-positive'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
}, await testDefaults({ reporter }))
|
||||
|
||||
expect(reporter.calledWithMatch({
|
||||
level: 'warn',
|
||||
@@ -319,17 +284,12 @@ test('unlink would remove global bin', async () => {
|
||||
)
|
||||
expect(fs.existsSync(path.resolve('bin/is-subdir'))).toBeTruthy()
|
||||
|
||||
await mutateModules(
|
||||
[
|
||||
{
|
||||
dependencyNames: ['is-subdir'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
],
|
||||
opts
|
||||
)
|
||||
await mutateModulesInSingleProject({
|
||||
dependencyNames: ['is-subdir'],
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: process.cwd(),
|
||||
}, opts)
|
||||
|
||||
expect(fs.existsSync(path.resolve('bin/is-subdir'))).toBeFalsy()
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import findWorkspacePackages from '@pnpm/find-workspace-packages'
|
||||
import findWorkspacePackages, { Project } from '@pnpm/find-workspace-packages'
|
||||
import matcher from '@pnpm/matcher'
|
||||
import createPkgGraph, { Package, PackageNode } from 'pkgs-graph'
|
||||
import isSubdir from 'is-subdir'
|
||||
@@ -29,6 +29,12 @@ interface FilteredGraph<T> {
|
||||
unmatchedFilters: string[]
|
||||
}
|
||||
|
||||
export interface ReadProjectsResult {
|
||||
allProjects: Project[]
|
||||
allProjectsGraph: PackageGraph<Project>
|
||||
selectedProjectsGraph: PackageGraph<Project>
|
||||
}
|
||||
|
||||
export async function readProjects (
|
||||
workspaceDir: string,
|
||||
pkgSelectors: PackageSelector[],
|
||||
@@ -37,9 +43,9 @@ export async function readProjects (
|
||||
linkWorkspacePackages?: boolean
|
||||
changedFilesIgnorePattern?: string[]
|
||||
}
|
||||
) {
|
||||
): Promise<ReadProjectsResult> {
|
||||
const allProjects = await findWorkspacePackages(workspaceDir, { engineStrict: opts?.engineStrict })
|
||||
const { selectedProjectsGraph } = await filterPkgsBySelectorObjects(
|
||||
const { allProjectsGraph, selectedProjectsGraph } = await filterPkgsBySelectorObjects(
|
||||
allProjects,
|
||||
pkgSelectors,
|
||||
{
|
||||
@@ -48,7 +54,7 @@ export async function readProjects (
|
||||
changedFilesIgnorePattern: opts?.changedFilesIgnorePattern,
|
||||
}
|
||||
)
|
||||
return { allProjects, selectedProjectsGraph }
|
||||
return { allProjects, allProjectsGraph, selectedProjectsGraph }
|
||||
}
|
||||
|
||||
export interface FilterPackagesOptions {
|
||||
|
||||
@@ -7,14 +7,14 @@ import readYamlFile from 'read-yaml-file'
|
||||
|
||||
export { Project }
|
||||
|
||||
export default async (
|
||||
export default async function (
|
||||
workspaceRoot: string,
|
||||
opts?: {
|
||||
engineStrict?: boolean
|
||||
nodeVersion?: string
|
||||
patterns?: string[]
|
||||
}
|
||||
) => {
|
||||
): Promise<Project[]> {
|
||||
const pkgs = await findWorkspacePackagesNoCheck(workspaceRoot, opts)
|
||||
for (const pkg of pkgs) {
|
||||
packageIsInstallable(pkg.dir, pkg.manifest, opts ?? {})
|
||||
|
||||
@@ -20,6 +20,7 @@ import rimraf from '@zkochan/rimraf'
|
||||
import pathAbsolute from 'path-absolute'
|
||||
import clone from 'ramda/src/clone'
|
||||
import equals from 'ramda/src/equals'
|
||||
import fromPairs from 'ramda/src/fromPairs'
|
||||
import checkCompatibility from './checkCompatibility'
|
||||
import UnexpectedStoreError from './checkCompatibility/UnexpectedStoreError'
|
||||
import UnexpectedVirtualStoreDirError from './checkCompatibility/UnexpectedVirtualStoreDirError'
|
||||
@@ -27,7 +28,7 @@ import readLockfileFile from './readLockfiles'
|
||||
|
||||
export { UnexpectedStoreError, UnexpectedVirtualStoreDirError }
|
||||
|
||||
export interface PnpmContext<T> {
|
||||
export interface PnpmContext {
|
||||
currentLockfile: Lockfile
|
||||
currentLockfileIsUpToDate: boolean
|
||||
existsCurrentLockfile: boolean
|
||||
@@ -39,10 +40,10 @@ export interface PnpmContext<T> {
|
||||
include: IncludedDependencies
|
||||
modulesFile: Modules | null
|
||||
pendingBuilds: string[]
|
||||
projects: Array<{
|
||||
projects: Record<string, {
|
||||
modulesDir: string
|
||||
id: string
|
||||
} & HookOptions & T & Required<ProjectOptions>>
|
||||
} & HookOptions & Required<ProjectOptions>>
|
||||
rootModulesDir: string
|
||||
hoistPattern: string[] | undefined
|
||||
hoistedModulesDir: string
|
||||
@@ -56,6 +57,7 @@ export interface PnpmContext<T> {
|
||||
}
|
||||
|
||||
export interface ProjectOptions {
|
||||
buildIndex: number
|
||||
binsDir?: string
|
||||
manifest: ProjectManifest
|
||||
modulesDir?: string
|
||||
@@ -67,6 +69,7 @@ interface HookOptions {
|
||||
}
|
||||
|
||||
export interface GetContextOptions {
|
||||
allProjects: Array<ProjectOptions & HookOptions>
|
||||
force: boolean
|
||||
forceNewModules?: boolean
|
||||
forceSharedLockfile: boolean
|
||||
@@ -91,12 +94,11 @@ export interface GetContextOptions {
|
||||
forcePublicHoistPattern?: boolean
|
||||
}
|
||||
|
||||
export default async function getContext<T> (
|
||||
projects: Array<ProjectOptions & HookOptions & T>,
|
||||
export default async function getContext (
|
||||
opts: GetContextOptions
|
||||
): Promise<PnpmContext<T>> {
|
||||
): Promise<PnpmContext> {
|
||||
const modulesDir = opts.modulesDir ?? 'node_modules'
|
||||
let importersContext = await readProjectsContext(projects, { lockfileDir: opts.lockfileDir, modulesDir })
|
||||
let importersContext = await readProjectsContext(opts.allProjects, { lockfileDir: opts.lockfileDir, modulesDir })
|
||||
const virtualStoreDir = pathAbsolute(opts.virtualStoreDir ?? path.join(modulesDir, '.pnpm'), opts.lockfileDir)
|
||||
|
||||
if (importersContext.modules != null) {
|
||||
@@ -118,7 +120,7 @@ export default async function getContext<T> (
|
||||
publicHoistPattern: opts.publicHoistPattern,
|
||||
})
|
||||
if (purged) {
|
||||
importersContext = await readProjectsContext(projects, {
|
||||
importersContext = await readProjectsContext(opts.allProjects, {
|
||||
lockfileDir: opts.lockfileDir,
|
||||
modulesDir,
|
||||
})
|
||||
@@ -127,7 +129,7 @@ export default async function getContext<T> (
|
||||
|
||||
await fs.mkdir(opts.storeDir, { recursive: true })
|
||||
|
||||
projects.forEach((project) => {
|
||||
opts.allProjects.forEach((project) => {
|
||||
packageManifestLogger.debug({
|
||||
initial: project.manifest,
|
||||
prefix: project.rootDir,
|
||||
@@ -148,7 +150,7 @@ export default async function getContext<T> (
|
||||
extraBinPaths.unshift(path.join(hoistedModulesDir, '.bin'))
|
||||
}
|
||||
const hoistPattern = importersContext.currentHoistPattern ?? opts.hoistPattern
|
||||
const ctx: PnpmContext<T> = {
|
||||
const ctx: PnpmContext = {
|
||||
extraBinPaths,
|
||||
extraNodePaths: getExtraNodePaths({ nodeLinker: opts.nodeLinker, hoistPattern, virtualStoreDir }),
|
||||
hoistedDependencies: importersContext.hoistedDependencies,
|
||||
@@ -158,7 +160,7 @@ export default async function getContext<T> (
|
||||
lockfileDir: opts.lockfileDir,
|
||||
modulesFile: importersContext.modules,
|
||||
pendingBuilds: importersContext.pendingBuilds,
|
||||
projects: importersContext.projects,
|
||||
projects: fromPairs(importersContext.projects.map((project) => [project.rootDir, project])),
|
||||
publicHoistPattern: importersContext.currentPublicHoistPattern ?? opts.publicHoistPattern,
|
||||
registries: {
|
||||
...opts.registries,
|
||||
|
||||
@@ -63,6 +63,7 @@ import equals from 'ramda/src/equals'
|
||||
import fromPairs from 'ramda/src/fromPairs'
|
||||
import isEmpty from 'ramda/src/isEmpty'
|
||||
import omit from 'ramda/src/omit'
|
||||
import pick from 'ramda/src/pick'
|
||||
import props from 'ramda/src/props'
|
||||
import union from 'ramda/src/union'
|
||||
import realpathMissing from 'realpath-missing'
|
||||
@@ -108,7 +109,8 @@ export interface HeadlessOptions {
|
||||
ignoreScripts: boolean
|
||||
ignorePackageManifest?: boolean
|
||||
include: IncludedDependencies
|
||||
projects: Project[]
|
||||
selectedProjectDirs: string[]
|
||||
allProjects: Record<string, Project>
|
||||
prunedAt?: string
|
||||
hoistedDependencies: HoistedDependencies
|
||||
hoistPattern?: string[]
|
||||
@@ -171,9 +173,10 @@ export default async (opts: HeadlessOptions) => {
|
||||
const currentLockfile = opts.currentLockfile ?? await readCurrentLockfile(virtualStoreDir, { ignoreIncompatible: false })
|
||||
const hoistedModulesDir = path.join(virtualStoreDir, 'node_modules')
|
||||
const publicHoistedModulesDir = rootModulesDir
|
||||
const selectedProjects = Object.values(pick(opts.selectedProjectDirs, opts.allProjects))
|
||||
|
||||
if (!opts.ignorePackageManifest) {
|
||||
for (const { id, manifest, rootDir } of opts.projects) {
|
||||
for (const { id, manifest, rootDir } of selectedProjects) {
|
||||
if (!satisfiesPackageManifest(wantedLockfile, manifest, id, { autoInstallPeers: opts.autoInstallPeers })) {
|
||||
throw new PnpmError('OUTDATED_LOCKFILE',
|
||||
`Cannot install with "frozen-lockfile" because ${WANTED_LOCKFILE} is not up to date with ` +
|
||||
@@ -201,7 +204,7 @@ export default async (opts: HeadlessOptions) => {
|
||||
if (opts.nodeLinker !== 'hoisted') {
|
||||
if (currentLockfile != null && !opts.ignorePackageManifest) {
|
||||
await prune(
|
||||
opts.projects,
|
||||
selectedProjects,
|
||||
{
|
||||
currentLockfile,
|
||||
dryRun: false,
|
||||
@@ -239,7 +242,7 @@ export default async (opts: HeadlessOptions) => {
|
||||
}
|
||||
const importerIds = (opts.ignorePackageManifest === true || opts.nodeLinker === 'hoisted')
|
||||
? Object.keys(wantedLockfile.importers)
|
||||
: opts.projects.map(({ id }) => id)
|
||||
: selectedProjects.map(({ id }) => id)
|
||||
const filteredLockfile = filterLockfileByImportersAndEngine(wantedLockfile, importerIds, {
|
||||
...filterOpts,
|
||||
currentEngine: opts.currentEngine,
|
||||
@@ -279,7 +282,7 @@ export default async (opts: HeadlessOptions) => {
|
||||
)
|
||||
if (opts.enablePnp) {
|
||||
const importerNames = fromPairs(
|
||||
opts.projects.map(({ manifest, id }) => [id, manifest.name ?? id])
|
||||
selectedProjects.map(({ manifest, id }) => [id, manifest.name ?? id])
|
||||
)
|
||||
await writePnpFile(filteredLockfile, {
|
||||
importerNames,
|
||||
@@ -321,7 +324,7 @@ export default async (opts: HeadlessOptions) => {
|
||||
directDependenciesByImporterId: symlinkedDirectDependenciesByImporterId!,
|
||||
filteredLockfile,
|
||||
lockfileDir,
|
||||
projects: opts.projects,
|
||||
projects: selectedProjects,
|
||||
registries: opts.registries,
|
||||
symlink: opts.symlink,
|
||||
})
|
||||
@@ -389,7 +392,7 @@ export default async (opts: HeadlessOptions) => {
|
||||
directDependenciesByImporterId,
|
||||
filteredLockfile,
|
||||
lockfileDir,
|
||||
projects: opts.projects,
|
||||
projects: selectedProjects,
|
||||
registries: opts.registries,
|
||||
symlink: opts.symlink,
|
||||
})
|
||||
@@ -397,7 +400,7 @@ export default async (opts: HeadlessOptions) => {
|
||||
}
|
||||
|
||||
if (opts.ignoreScripts) {
|
||||
for (const { id, manifest } of opts.projects) {
|
||||
for (const { id, manifest } of selectedProjects) {
|
||||
if (opts.ignoreScripts && ((manifest?.scripts) != null) &&
|
||||
(manifest.scripts.preinstall ?? manifest.scripts.prepublish ??
|
||||
manifest.scripts.install ??
|
||||
@@ -457,7 +460,7 @@ export default async (opts: HeadlessOptions) => {
|
||||
})
|
||||
}
|
||||
|
||||
const projectsToBeBuilt = extendProjectsWithTargetDirs(opts.projects, wantedLockfile, {
|
||||
const projectsToBeBuilt = extendProjectsWithTargetDirs(selectedProjects, wantedLockfile, {
|
||||
pkgLocationByDepPath,
|
||||
virtualStoreDir,
|
||||
})
|
||||
@@ -465,7 +468,7 @@ export default async (opts: HeadlessOptions) => {
|
||||
if (opts.enableModulesDir !== false) {
|
||||
/** Skip linking and due to no project manifest */
|
||||
if (!opts.ignorePackageManifest) {
|
||||
await Promise.all(opts.projects.map(async (project) => {
|
||||
await Promise.all(selectedProjects.map(async (project) => {
|
||||
if (opts.publicHoistPattern?.length && path.relative(opts.lockfileDir, project.rootDir) === '') {
|
||||
await linkBinsOfImporter(project, {
|
||||
extraNodePaths: opts.extraNodePaths,
|
||||
@@ -540,9 +543,10 @@ export default async (opts: HeadlessOptions) => {
|
||||
}
|
||||
}
|
||||
|
||||
type SymlinkDirectDependenciesOpts = Pick<HeadlessOptions, 'projects' | 'registries' | 'symlink' | 'lockfileDir'> & {
|
||||
type SymlinkDirectDependenciesOpts = Pick<HeadlessOptions, 'registries' | 'symlink' | 'lockfileDir'> & {
|
||||
filteredLockfile: Lockfile
|
||||
directDependenciesByImporterId: DirectDependenciesByImporterId
|
||||
projects: Project[]
|
||||
}
|
||||
|
||||
async function symlinkDirectDependencies (
|
||||
|
||||
@@ -14,8 +14,6 @@ import headless from '@pnpm/headless'
|
||||
import { readWantedLockfile } from '@pnpm/lockfile-file'
|
||||
import { read as readModulesYaml } from '@pnpm/modules-yaml'
|
||||
import { tempDir } from '@pnpm/prepare'
|
||||
import { fromDir as readPackageJsonFromDir } from '@pnpm/read-package-json'
|
||||
import readprojectsContext from '@pnpm/read-projects-context'
|
||||
import { getIntegrity, REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
|
||||
import fixtures from '@pnpm/test-fixtures'
|
||||
import rimraf from '@zkochan/rimraf'
|
||||
@@ -657,22 +655,9 @@ test('installing with publicHoistPattern=* in a project with external lockfile',
|
||||
const lockfileDir = f.prepare('pkg-with-external-lockfile')
|
||||
const prefix = path.join(lockfileDir, 'pkg')
|
||||
|
||||
let { projects } = await readprojectsContext(
|
||||
[
|
||||
{
|
||||
rootDir: prefix,
|
||||
},
|
||||
],
|
||||
{ lockfileDir }
|
||||
)
|
||||
|
||||
projects = await Promise.all(
|
||||
projects.map(async (project) => ({ ...project, manifest: await readPackageJsonFromDir(project.rootDir) }))
|
||||
)
|
||||
|
||||
await headless(await testDefaults({
|
||||
lockfileDir,
|
||||
projects,
|
||||
projects: [prefix],
|
||||
publicHoistPattern: '*',
|
||||
}))
|
||||
|
||||
@@ -725,23 +710,11 @@ test.each([['isolated'], ['hoisted']])('using side effects cache with nodeLinker
|
||||
test.skip('using side effects cache and hoistPattern=*', async () => {
|
||||
const lockfileDir = f.prepare('side-effects-of-subdep')
|
||||
|
||||
const { projects } = await readprojectsContext(
|
||||
[
|
||||
{
|
||||
rootDir: lockfileDir,
|
||||
},
|
||||
],
|
||||
{ lockfileDir }
|
||||
)
|
||||
|
||||
// Right now, hardlink does not work with side effects, so we specify copy as the packageImportMethod
|
||||
// We disable verifyStoreIntegrity because we are going to change the cache
|
||||
const opts = await testDefaults({
|
||||
hoistPattern: '*',
|
||||
lockfileDir,
|
||||
projects: await Promise.all(
|
||||
projects.map(async (project) => ({ ...project, manifest: await readPackageJsonFromDir(project.rootDir) }))
|
||||
),
|
||||
sideEffectsCacheRead: true,
|
||||
sideEffectsCacheWrite: true,
|
||||
verifyStoreIntegrity: false,
|
||||
@@ -765,21 +738,10 @@ test.skip('using side effects cache and hoistPattern=*', async () => {
|
||||
test('installing in a workspace', async () => {
|
||||
const workspaceFixture = f.prepare('workspace')
|
||||
|
||||
let { projects } = await readprojectsContext(
|
||||
[
|
||||
{
|
||||
rootDir: path.join(workspaceFixture, 'foo'),
|
||||
},
|
||||
{
|
||||
rootDir: path.join(workspaceFixture, 'bar'),
|
||||
},
|
||||
],
|
||||
{ lockfileDir: workspaceFixture }
|
||||
)
|
||||
|
||||
projects = await Promise.all(
|
||||
projects.map(async (project) => ({ ...project, manifest: await readPackageJsonFromDir(project.rootDir) }))
|
||||
)
|
||||
const projects = [
|
||||
path.join(workspaceFixture, 'foo'),
|
||||
path.join(workspaceFixture, 'bar'),
|
||||
]
|
||||
|
||||
await headless(await testDefaults({
|
||||
lockfileDir: workspaceFixture,
|
||||
@@ -849,25 +811,13 @@ test('installing with node-linker=hoisted', async () => {
|
||||
test('installing in a workspace with node-linker=hoisted', async () => {
|
||||
const prefix = f.prepare('workspace2')
|
||||
|
||||
let { projects } = await readprojectsContext(
|
||||
[
|
||||
{
|
||||
rootDir: path.join(prefix, 'foo'),
|
||||
},
|
||||
{
|
||||
rootDir: path.join(prefix, 'bar'),
|
||||
},
|
||||
],
|
||||
{ lockfileDir: prefix }
|
||||
)
|
||||
|
||||
projects = await Promise.all(
|
||||
projects.map(async (project) => ({ ...project, manifest: await readPackageJsonFromDir(project.rootDir) }))
|
||||
)
|
||||
await headless(await testDefaults({
|
||||
lockfileDir: prefix,
|
||||
nodeLinker: 'hoisted',
|
||||
projects,
|
||||
projects: [
|
||||
path.join(prefix, 'foo'),
|
||||
path.join(prefix, 'bar'),
|
||||
],
|
||||
}))
|
||||
|
||||
expect(realpathSync('bar/node_modules/foo')).toBe(path.resolve('foo'))
|
||||
|
||||
@@ -2,10 +2,11 @@ import path from 'path'
|
||||
import createClient from '@pnpm/client'
|
||||
import { HeadlessOptions } from '@pnpm/headless'
|
||||
import createStore from '@pnpm/package-store'
|
||||
import { fromDir as readPackageJsonFromDir } from '@pnpm/read-package-json'
|
||||
import { safeReadPackageFromDir } from '@pnpm/read-package-json'
|
||||
import readProjectsContext from '@pnpm/read-projects-context'
|
||||
import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
|
||||
import storePath from '@pnpm/store-path'
|
||||
import fromPairs from 'ramda/src/fromPairs'
|
||||
import tempy from 'tempy'
|
||||
|
||||
const registry = `http://localhost:${REGISTRY_MOCK_PORT}/`
|
||||
@@ -28,11 +29,13 @@ export default async function testDefaults (
|
||||
const cacheDir = path.join(tmp, 'cache')
|
||||
const lockfileDir = opts?.lockfileDir ?? process.cwd()
|
||||
const { include, pendingBuilds, projects, registries } = await readProjectsContext(
|
||||
[
|
||||
{
|
||||
rootDir: lockfileDir,
|
||||
},
|
||||
],
|
||||
opts.projects
|
||||
? opts.projects.map((rootDir: string) => ({ rootDir }))
|
||||
: [
|
||||
{
|
||||
rootDir: lockfileDir,
|
||||
},
|
||||
],
|
||||
{ lockfileDir }
|
||||
)
|
||||
storeDir = await storePath({
|
||||
@@ -72,11 +75,10 @@ export default async function testDefaults (
|
||||
version: '1.0.0',
|
||||
},
|
||||
pendingBuilds,
|
||||
projects: opts.projects
|
||||
? opts.projects
|
||||
: await Promise.all(
|
||||
projects.map(async (project) => ({ ...project, manifest: await readPackageJsonFromDir(project.rootDir) }))
|
||||
),
|
||||
selectedProjectDirs: projects.map((project) => project.rootDir),
|
||||
allProjects: fromPairs(
|
||||
await Promise.all(projects.map(async (project) => [project.rootDir, { ...project, manifest: await safeReadPackageFromDir(project.rootDir) }]))
|
||||
),
|
||||
rawConfig: {},
|
||||
registries: registries ?? {
|
||||
default: registry,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { docsUrl } from '@pnpm/cli-utils'
|
||||
import { UNIVERSAL_OPTIONS } from '@pnpm/common-cli-options-help'
|
||||
import { Config } from '@pnpm/config'
|
||||
import { createOrConnectStoreController, CreateStoreControllerOptions } from '@pnpm/store-connection-manager'
|
||||
import { InstallOptions, mutateModules } from '@pnpm/core'
|
||||
import { InstallOptions, mutateModulesInSingleProject } from '@pnpm/core'
|
||||
import renderHelp from 'render-help'
|
||||
import { cliOptionsTypes } from './install'
|
||||
|
||||
@@ -47,15 +47,12 @@ export async function handler (
|
||||
// when including optional deps, production is also required when perform headless install
|
||||
optionalDependencies: opts.production !== false,
|
||||
}
|
||||
return mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: {},
|
||||
mutation: 'install',
|
||||
pruneDirectDependencies: true,
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], {
|
||||
return mutateModulesInSingleProject({
|
||||
manifest: {},
|
||||
mutation: 'install',
|
||||
pruneDirectDependencies: true,
|
||||
rootDir: process.cwd(),
|
||||
}, {
|
||||
...opts,
|
||||
ignorePackageManifest: true,
|
||||
include,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export default function getPinnedVersion (opts: { saveExact?: boolean, savePrefix?: string }) {
|
||||
export default function getPinnedVersion (opts: { saveExact?: boolean, savePrefix?: string }): 'major' | 'minor' | 'patch' {
|
||||
if (opts.saveExact === true || opts.savePrefix === '') return 'patch'
|
||||
return opts.savePrefix === '~' ? 'minor' : 'major'
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ export const commandNames = ['import']
|
||||
|
||||
export type ImportCommandOptions = Pick<Config,
|
||||
| 'allProjects'
|
||||
| 'allProjectsGraph'
|
||||
| 'selectedProjectsGraph'
|
||||
| 'workspaceDir'
|
||||
> & CreateStoreControllerOptions & Omit<InstallOptions, 'storeController' | 'lockfileOnly' | 'preferredVersions'>
|
||||
|
||||
@@ -269,6 +269,7 @@ export type InstallCommandOptions = Pick<Config,
|
||||
| 'saveProd'
|
||||
| 'saveWorkspaceProtocol'
|
||||
| 'lockfileIncludeTarballUrl'
|
||||
| 'allProjectsGraph'
|
||||
| 'selectedProjectsGraph'
|
||||
| 'sideEffectsCache'
|
||||
| 'sideEffectsCacheReadonly'
|
||||
|
||||
@@ -12,9 +12,8 @@ import { createOrConnectStoreController, CreateStoreControllerOptions } from '@p
|
||||
import { IncludedDependencies, Project } from '@pnpm/types'
|
||||
import {
|
||||
install,
|
||||
mutateModules,
|
||||
mutateModulesInSingleProject,
|
||||
MutateModulesOptions,
|
||||
MutatedProject,
|
||||
WorkspacePackages,
|
||||
} from '@pnpm/core'
|
||||
import logger from '@pnpm/logger'
|
||||
@@ -35,6 +34,7 @@ const OVERWRITE_UPDATE_OPTIONS = {
|
||||
|
||||
export type InstallDepsOptions = Pick<Config,
|
||||
| 'allProjects'
|
||||
| 'allProjectsGraph'
|
||||
| 'autoInstallPeers'
|
||||
| 'bail'
|
||||
| 'bin'
|
||||
@@ -149,6 +149,7 @@ when running add/update with the --workspace option')
|
||||
...opts,
|
||||
forceHoistPattern,
|
||||
forcePublicHoistPattern,
|
||||
allProjectsGraph: selectedProjectsGraph,
|
||||
selectedProjectsGraph,
|
||||
workspaceDir: opts.workspaceDir,
|
||||
},
|
||||
@@ -176,7 +177,7 @@ when running add/update with the --workspace option')
|
||||
}
|
||||
|
||||
const store = await createOrConnectStoreController(opts)
|
||||
const installOpts: MutateModulesOptions = {
|
||||
const installOpts: Omit<MutateModulesOptions, 'allProjects'> = {
|
||||
...opts,
|
||||
...getOptionsFromRootManifest(manifest),
|
||||
forceHoistPattern,
|
||||
@@ -234,18 +235,18 @@ when running add/update with the --workspace option')
|
||||
}
|
||||
}
|
||||
if (params?.length) {
|
||||
const mutatedProject: MutatedProject = {
|
||||
const mutatedProject = {
|
||||
allowNew: opts.allowNew,
|
||||
binsDir: opts.bin,
|
||||
dependencySelectors: params,
|
||||
manifest,
|
||||
mutation: 'installSome',
|
||||
mutation: 'installSome' as const,
|
||||
peer: opts.savePeer,
|
||||
pinnedVersion: getPinnedVersion(opts),
|
||||
rootDir: opts.dir,
|
||||
targetDependenciesField: getSaveType(opts),
|
||||
}
|
||||
const [updatedImporter] = await mutateModules([mutatedProject], installOpts)
|
||||
const updatedImporter = await mutateModulesInSingleProject(mutatedProject, installOpts)
|
||||
if (opts.save !== false) {
|
||||
await writeProjectManifest(updatedImporter.manifest)
|
||||
}
|
||||
@@ -270,6 +271,7 @@ when running add/update with the --workspace option')
|
||||
await recursive(allProjects, [], {
|
||||
...opts,
|
||||
...OVERWRITE_UPDATE_OPTIONS,
|
||||
allProjectsGraph: opts.allProjectsGraph!,
|
||||
selectedProjectsGraph,
|
||||
workspaceDir: opts.workspaceDir, // Otherwise TypeScript doesn't understand that is not undefined
|
||||
}, 'install')
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
InstallOptions,
|
||||
MutatedProject,
|
||||
mutateModules,
|
||||
ProjectOptions,
|
||||
} from '@pnpm/core'
|
||||
import camelcaseKeys from 'camelcase-keys'
|
||||
import isSubdir from 'is-subdir'
|
||||
@@ -79,6 +80,7 @@ type RecursiveOptions = CreateStoreControllerOptions & Pick<Config,
|
||||
ignoredPackages?: Set<string>
|
||||
update?: boolean
|
||||
useBetaCli?: boolean
|
||||
allProjectsGraph: ProjectsGraph
|
||||
selectedProjectsGraph: ProjectsGraph
|
||||
preferredVersions?: PreferredVersions
|
||||
pruneDirectDependencies?: boolean
|
||||
@@ -107,17 +109,10 @@ export default async function recursive (
|
||||
if (pkgs.length === 0) {
|
||||
return false
|
||||
}
|
||||
const manifestsByPath: { [dir: string]: Omit<Project, 'dir'> } = {}
|
||||
for (const { dir, manifest, writeProjectManifest } of allProjects) {
|
||||
manifestsByPath[dir] = { manifest, writeProjectManifest }
|
||||
}
|
||||
const manifestsByPath = getManifestsByPath(allProjects)
|
||||
|
||||
const throwOnFail = throwOnCommandFail.bind(null, `pnpm recursive ${cmdFullName}`)
|
||||
|
||||
const chunks = opts.sort !== false
|
||||
? sortPackages(opts.selectedProjectsGraph)
|
||||
: [Object.keys(opts.selectedProjectsGraph).sort()]
|
||||
|
||||
const store = await createOrConnectStoreController(opts)
|
||||
|
||||
const workspacePackages = cmdFullName !== 'unlink'
|
||||
@@ -126,6 +121,7 @@ export default async function recursive (
|
||||
const targetDependenciesField = getSaveType(opts)
|
||||
const installOpts = Object.assign(opts, {
|
||||
...getOptionsFromRootManifest(manifestsByPath[opts.lockfileDir ?? opts.dir]?.manifest ?? {}),
|
||||
allProjects: getAllProjects(manifestsByPath, opts.allProjectsGraph, opts.sort),
|
||||
linkWorkspacePackagesDepth: opts.linkWorkspacePackages === 'deep' ? Infinity : opts.linkWorkspacePackages ? 0 : -1,
|
||||
ownLifecycleHooksStdio: 'pipe',
|
||||
peer: opts.savePeer,
|
||||
@@ -147,25 +143,6 @@ export default async function recursive (
|
||||
|
||||
const memReadLocalConfig = mem(readLocalConfig)
|
||||
|
||||
async function getImporters () {
|
||||
const importers = [] as Array<{ buildIndex: number, manifest: ProjectManifest, rootDir: string }>
|
||||
await Promise.all(chunks.map(async (prefixes: string[], buildIndex) => {
|
||||
if (opts.ignoredPackages != null) {
|
||||
prefixes = prefixes.filter((prefix) => !opts.ignoredPackages!.has(prefix))
|
||||
}
|
||||
return Promise.all(
|
||||
prefixes.map(async (prefix) => {
|
||||
importers.push({
|
||||
buildIndex,
|
||||
manifest: manifestsByPath[prefix].manifest,
|
||||
rootDir: prefix,
|
||||
})
|
||||
})
|
||||
)
|
||||
}))
|
||||
return importers
|
||||
}
|
||||
|
||||
const updateToLatest = opts.update && opts.latest
|
||||
const includeDirect = opts.includeDirect ?? {
|
||||
dependencies: true,
|
||||
@@ -187,7 +164,7 @@ export default async function recursive (
|
||||
}
|
||||
// For a workspace with shared lockfile
|
||||
if (opts.lockfileDir && ['add', 'install', 'remove', 'update', 'import'].includes(cmdFullName)) {
|
||||
let importers = await getImporters()
|
||||
let importers = getImporters(opts)
|
||||
const calculatedRepositoryRoot = await fs.realpath(calculateRepositoryRoot(opts.workspaceDir, importers.map(x => x.rootDir)))
|
||||
const isFromWorkspace = isSubdir.bind(null, calculatedRepositoryRoot)
|
||||
importers = await pFilter(importers, async ({ rootDir }: { rootDir: string }) => isFromWorkspace(await fs.realpath(rootDir)))
|
||||
@@ -206,7 +183,7 @@ export default async function recursive (
|
||||
}
|
||||
const writeProjectManifests = [] as Array<(manifest: ProjectManifest) => Promise<void>>
|
||||
const mutatedImporters = [] as MutatedProject[]
|
||||
await Promise.all(importers.map(async ({ buildIndex, rootDir }) => {
|
||||
await Promise.all(importers.map(async ({ rootDir }) => {
|
||||
const localConfig = await memReadLocalConfig(rootDir)
|
||||
const modulesDir = localConfig.modulesDir ?? opts.modulesDir
|
||||
const { manifest, writeProjectManifest } = manifestsByPath[rootDir]
|
||||
@@ -241,7 +218,6 @@ export default async function recursive (
|
||||
case 'uninstallSome':
|
||||
mutatedImporters.push({
|
||||
dependencyNames: currentInput,
|
||||
manifest,
|
||||
modulesDir,
|
||||
mutation,
|
||||
rootDir,
|
||||
@@ -252,7 +228,6 @@ export default async function recursive (
|
||||
mutatedImporters.push({
|
||||
allowNew: cmdFullName === 'install' || cmdFullName === 'add',
|
||||
dependencySelectors: currentInput,
|
||||
manifest,
|
||||
modulesDir,
|
||||
mutation,
|
||||
peer: opts.savePeer,
|
||||
@@ -266,8 +241,6 @@ export default async function recursive (
|
||||
return
|
||||
case 'install':
|
||||
mutatedImporters.push({
|
||||
buildIndex,
|
||||
manifest,
|
||||
modulesDir,
|
||||
mutation,
|
||||
pruneDirectDependencies: opts.pruneDirectDependencies,
|
||||
@@ -292,9 +265,7 @@ export default async function recursive (
|
||||
return true
|
||||
}
|
||||
|
||||
const pkgPaths = chunks.length === 0
|
||||
? chunks[0]
|
||||
: Object.keys(opts.selectedProjectsGraph).sort()
|
||||
const pkgPaths = Object.keys(opts.selectedProjectsGraph).sort()
|
||||
|
||||
const limitInstallation = pLimit(opts.workspaceConcurrency ?? 4)
|
||||
await Promise.all(pkgPaths.map(async (rootDir: string) =>
|
||||
@@ -347,7 +318,6 @@ export default async function recursive (
|
||||
const [{ manifest: newManifest }] = await mutateModules([
|
||||
{
|
||||
dependencyNames: currentInput,
|
||||
manifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir,
|
||||
},
|
||||
@@ -434,7 +404,6 @@ async function unlink (manifest: ProjectManifest, opts: any) { // eslint-disable
|
||||
return mutateModules(
|
||||
[
|
||||
{
|
||||
manifest,
|
||||
mutation: 'unlink',
|
||||
rootDir: opts.dir,
|
||||
},
|
||||
@@ -448,7 +417,6 @@ async function unlinkPkgs (dependencyNames: string[], manifest: ProjectManifest,
|
||||
[
|
||||
{
|
||||
dependencyNames,
|
||||
manifest,
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: opts.dir,
|
||||
},
|
||||
@@ -535,3 +503,31 @@ export function createMatcher (params: string[]): UpdateDepsMatcher {
|
||||
export function makeIgnorePatterns (ignoredDependencies: string[]): string[] {
|
||||
return ignoredDependencies.map(depName => `!${depName}`)
|
||||
}
|
||||
|
||||
function getAllProjects (manifestsByPath: ManifestsByPath, allProjectsGraph: ProjectsGraph, sort?: boolean): ProjectOptions[] {
|
||||
const chunks = sort !== false
|
||||
? sortPackages(allProjectsGraph)
|
||||
: [Object.keys(allProjectsGraph).sort()]
|
||||
return chunks.map((prefixes: string[], buildIndex) => prefixes.map((rootDir) => ({
|
||||
buildIndex,
|
||||
manifest: manifestsByPath[rootDir].manifest,
|
||||
rootDir,
|
||||
}))).flat()
|
||||
}
|
||||
|
||||
interface ManifestsByPath { [dir: string]: Omit<Project, 'dir'> }
|
||||
|
||||
function getManifestsByPath (projects: Project[]) {
|
||||
return projects.reduce((manifestsByPath, { dir, manifest, writeProjectManifest }) => {
|
||||
manifestsByPath[dir] = { manifest, writeProjectManifest }
|
||||
return manifestsByPath
|
||||
}, {})
|
||||
}
|
||||
|
||||
function getImporters (opts: Pick<RecursiveOptions, 'selectedProjectsGraph' | 'ignoredPackages'>) {
|
||||
let rootDirs = Object.keys(opts.selectedProjectsGraph)
|
||||
if (opts.ignoredPackages != null) {
|
||||
rootDirs = rootDirs.filter((rootDir) => !opts.ignoredPackages!.has(rootDir))
|
||||
}
|
||||
return rootDirs.map((rootDir) => ({ rootDir }))
|
||||
}
|
||||
|
||||
@@ -11,9 +11,7 @@ import findWorkspacePackages, { arrayOfWorkspacePackagesToMap } from '@pnpm/find
|
||||
import { getAllDependenciesFromManifest } from '@pnpm/manifest-utils'
|
||||
import { createOrConnectStoreController, CreateStoreControllerOptions } from '@pnpm/store-connection-manager'
|
||||
import { DependenciesField } from '@pnpm/types'
|
||||
import {
|
||||
mutateModules,
|
||||
} from '@pnpm/core'
|
||||
import { mutateModulesInSingleProject } from '@pnpm/core'
|
||||
import pick from 'ramda/src/pick'
|
||||
import without from 'ramda/src/without'
|
||||
import renderHelp from 'render-help'
|
||||
@@ -129,6 +127,7 @@ export const completion: CompletionFunc = async (cliOpts, params) => {
|
||||
export async function handler (
|
||||
opts: CreateStoreControllerOptions & Pick<Config,
|
||||
| 'allProjects'
|
||||
| 'allProjectsGraph'
|
||||
| 'bail'
|
||||
| 'bin'
|
||||
| 'dev'
|
||||
@@ -161,7 +160,13 @@ export async function handler (
|
||||
optionalDependencies: opts.optional !== false,
|
||||
}
|
||||
if (opts.recursive && (opts.allProjects != null) && (opts.selectedProjectsGraph != null) && opts.workspaceDir) {
|
||||
await recursive(opts.allProjects, params, { ...opts, include, selectedProjectsGraph: opts.selectedProjectsGraph, workspaceDir: opts.workspaceDir }, 'remove')
|
||||
await recursive(opts.allProjects, params, {
|
||||
...opts,
|
||||
allProjectsGraph: opts.allProjectsGraph!,
|
||||
include,
|
||||
selectedProjectsGraph: opts.selectedProjectsGraph,
|
||||
workspaceDir: opts.workspaceDir,
|
||||
}, 'remove')
|
||||
return
|
||||
}
|
||||
const store = await createOrConnectStoreController(opts)
|
||||
@@ -192,17 +197,15 @@ export async function handler (
|
||||
targetDependenciesField,
|
||||
})
|
||||
}
|
||||
const [mutationResult] = await mutateModules(
|
||||
[
|
||||
{
|
||||
binsDir: opts.bin,
|
||||
dependencyNames: params,
|
||||
manifest: currentManifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: opts.dir,
|
||||
targetDependenciesField,
|
||||
},
|
||||
],
|
||||
const mutationResult = await mutateModulesInSingleProject(
|
||||
{
|
||||
binsDir: opts.bin,
|
||||
dependencyNames: params,
|
||||
manifest: currentManifest,
|
||||
mutation: 'uninstallSome',
|
||||
rootDir: opts.dir,
|
||||
targetDependenciesField,
|
||||
},
|
||||
removeOpts
|
||||
)
|
||||
await writeProjectManifest(mutationResult.manifest)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { docsUrl, readProjectManifestOnly } from '@pnpm/cli-utils'
|
||||
import { UNIVERSAL_OPTIONS } from '@pnpm/common-cli-options-help'
|
||||
import { Config } from '@pnpm/config'
|
||||
import { createOrConnectStoreController, CreateStoreControllerOptions } from '@pnpm/store-connection-manager'
|
||||
import { mutateModules } from '@pnpm/core'
|
||||
import { mutateModulesInSingleProject } from '@pnpm/core'
|
||||
import renderHelp from 'render-help'
|
||||
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||
import { cliOptionsTypes, rcOptionsTypes } from './install'
|
||||
@@ -44,6 +44,7 @@ export async function handler (
|
||||
opts: CreateStoreControllerOptions &
|
||||
Pick<Config,
|
||||
| 'allProjects'
|
||||
| 'allProjectsGraph'
|
||||
| 'bail'
|
||||
| 'bin'
|
||||
| 'engineStrict'
|
||||
@@ -61,7 +62,12 @@ export async function handler (
|
||||
params: string[]
|
||||
) {
|
||||
if (opts.recursive && (opts.allProjects != null) && (opts.selectedProjectsGraph != null) && opts.workspaceDir) {
|
||||
await recursive(opts.allProjects, params, { ...opts, selectedProjectsGraph: opts.selectedProjectsGraph, workspaceDir: opts.workspaceDir }, 'unlink')
|
||||
await recursive(opts.allProjects, params, {
|
||||
...opts,
|
||||
allProjectsGraph: opts.allProjectsGraph!,
|
||||
selectedProjectsGraph: opts.selectedProjectsGraph,
|
||||
workspaceDir: opts.workspaceDir,
|
||||
}, 'unlink')
|
||||
return
|
||||
}
|
||||
const store = await createOrConnectStoreController(opts)
|
||||
@@ -73,20 +79,16 @@ export async function handler (
|
||||
})
|
||||
|
||||
if (!params || (params.length === 0)) {
|
||||
return mutateModules([
|
||||
{
|
||||
dependencyNames: params,
|
||||
manifest: await readProjectManifestOnly(opts.dir, opts),
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: opts.dir,
|
||||
},
|
||||
], unlinkOpts)
|
||||
}
|
||||
return mutateModules([
|
||||
{
|
||||
return mutateModulesInSingleProject({
|
||||
dependencyNames: params,
|
||||
manifest: await readProjectManifestOnly(opts.dir, opts),
|
||||
mutation: 'unlink',
|
||||
mutation: 'unlinkSome',
|
||||
rootDir: opts.dir,
|
||||
},
|
||||
], unlinkOpts)
|
||||
}, unlinkOpts)
|
||||
}
|
||||
return mutateModulesInSingleProject({
|
||||
manifest: await readProjectManifestOnly(opts.dir, opts),
|
||||
mutation: 'unlink',
|
||||
rootDir: opts.dir,
|
||||
}, unlinkOpts)
|
||||
}
|
||||
|
||||
@@ -42,10 +42,11 @@ const DEFAULT_OPTS = {
|
||||
|
||||
test('import from shared yarn.lock of monorepo', async () => {
|
||||
f.prepare('workspace-has-shared-yarn-lock')
|
||||
const { allProjects, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
await importCommand.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjects: allProjects as any, // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
allProjectsGraph,
|
||||
selectedProjectsGraph,
|
||||
workspaceDir: process.cwd(),
|
||||
lockfileDir: process.cwd(),
|
||||
@@ -64,10 +65,11 @@ test('import from shared yarn.lock of monorepo', async () => {
|
||||
|
||||
test('import from shared package-lock.json of monorepo', async () => {
|
||||
f.prepare('workspace-has-shared-package-lock-json')
|
||||
const { allProjects, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
await importCommand.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjects: allProjects as any, // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
allProjectsGraph,
|
||||
selectedProjectsGraph,
|
||||
workspaceDir: process.cwd(),
|
||||
lockfileDir: process.cwd(),
|
||||
@@ -86,10 +88,11 @@ test('import from shared package-lock.json of monorepo', async () => {
|
||||
|
||||
test('import from shared npm-shrinkwrap.json of monorepo', async () => {
|
||||
f.prepare('workspace-has-shared-npm-shrinkwrap-json')
|
||||
const { allProjects, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
await importCommand.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjects: allProjects as any, // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
allProjectsGraph,
|
||||
selectedProjectsGraph,
|
||||
workspaceDir: process.cwd(),
|
||||
lockfileDir: process.cwd(),
|
||||
|
||||
@@ -26,10 +26,11 @@ test('recursive linking/unlinking', async () => {
|
||||
},
|
||||
])
|
||||
|
||||
const { allProjects, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -47,6 +48,7 @@ test('recursive linking/unlinking', async () => {
|
||||
await unlink.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -87,10 +89,11 @@ test('recursive unlink specific package', async () => {
|
||||
},
|
||||
])
|
||||
|
||||
const { allProjects, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -108,6 +111,7 @@ test('recursive unlink specific package', async () => {
|
||||
await unlink.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
|
||||
@@ -34,10 +34,11 @@ test('recursive add/remove', async () => {
|
||||
},
|
||||
])
|
||||
|
||||
const { allProjects, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -51,6 +52,7 @@ test('recursive add/remove', async () => {
|
||||
await add.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -63,6 +65,7 @@ test('recursive add/remove', async () => {
|
||||
await remove.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -92,10 +95,11 @@ test('recursive add/remove in workspace with many lockfiles', async () => {
|
||||
},
|
||||
])
|
||||
|
||||
const { allProjects, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -110,6 +114,7 @@ test('recursive add/remove in workspace with many lockfiles', async () => {
|
||||
await add.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -122,6 +127,7 @@ test('recursive add/remove in workspace with many lockfiles', async () => {
|
||||
await remove.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -328,10 +334,11 @@ test('second run of `recursive install` after package.json has been edited manua
|
||||
},
|
||||
])
|
||||
|
||||
const { allProjects, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -350,6 +357,7 @@ test('second run of `recursive install` after package.json has been edited manua
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -597,10 +605,11 @@ test('recursive install on workspace with custom lockfile-dir', async () => {
|
||||
])
|
||||
|
||||
const lockfileDir = path.resolve('_')
|
||||
const { allProjects, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
lockfileDir,
|
||||
recursive: true,
|
||||
@@ -634,10 +643,11 @@ test('recursive install in a monorepo with different modules directories', async
|
||||
await fs.writeFile('project-1/.npmrc', 'modules-dir=modules_1', 'utf8')
|
||||
await fs.writeFile('project-2/.npmrc', 'modules-dir=modules_2', 'utf8')
|
||||
|
||||
const { allProjects, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
@@ -702,11 +712,12 @@ test('installing in monorepo with shared lockfile should work on virtual drives'
|
||||
const virtualPath = process.cwd() + '-virtual-disk'
|
||||
// symlink simulates windows' subst
|
||||
await symlinkDir(process.cwd(), virtualPath)
|
||||
const { allProjects, selectedProjectsGraph } = await readProjects(virtualPath, [])
|
||||
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(virtualPath, [])
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
lockfileDir: virtualPath,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
dir: virtualPath,
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
|
||||
@@ -77,7 +77,7 @@ type PackageSelector = string | {
|
||||
}
|
||||
|
||||
export async function rebuildSelectedPkgs (
|
||||
projects: Array<{ manifest: ProjectManifest, rootDir: string }>,
|
||||
projects: Array<{ buildIndex: number, manifest: ProjectManifest, rootDir: string }>,
|
||||
pkgSpecs: string[],
|
||||
maybeOpts: RebuildOptions
|
||||
) {
|
||||
@@ -86,7 +86,7 @@ export async function rebuildSelectedPkgs (
|
||||
streamParser.on('data', reporter)
|
||||
}
|
||||
const opts = await extendOptions(maybeOpts)
|
||||
const ctx = await getContext(projects, opts)
|
||||
const ctx = await getContext({ ...opts, allProjects: projects })
|
||||
|
||||
if (!ctx.currentLockfile || (ctx.currentLockfile.packages == null)) return
|
||||
const packages = ctx.currentLockfile.packages
|
||||
@@ -131,7 +131,7 @@ export async function rebuildProjects (
|
||||
streamParser.on('data', reporter)
|
||||
}
|
||||
const opts = await extendOptions(maybeOpts)
|
||||
const ctx = await getContext(projects, opts)
|
||||
const ctx = await getContext({ ...opts, allProjects: projects })
|
||||
|
||||
let idsToRebuild: string[] = []
|
||||
|
||||
@@ -164,11 +164,11 @@ export async function rebuildProjects (
|
||||
}
|
||||
await runLifecycleHooksConcurrently(
|
||||
['preinstall', 'install', 'postinstall', 'prepublish', 'prepare'],
|
||||
ctx.projects,
|
||||
Object.values(ctx.projects),
|
||||
opts.childConcurrency || 5,
|
||||
scriptsOpts
|
||||
)
|
||||
for (const { id, manifest } of ctx.projects) {
|
||||
for (const { id, manifest } of Object.values(ctx.projects)) {
|
||||
if (((manifest?.scripts) != null) && (!opts.pending || ctx.pendingBuilds.includes(id))) {
|
||||
ctx.pendingBuilds.splice(ctx.pendingBuilds.indexOf(id), 1)
|
||||
}
|
||||
@@ -227,7 +227,7 @@ async function _rebuild (
|
||||
virtualStoreDir: string
|
||||
rootModulesDir: string
|
||||
currentLockfile: Lockfile
|
||||
projects: Array<{ id: string, rootDir: string }>
|
||||
projects: Record<string, { id: string, rootDir: string }>
|
||||
extraBinPaths: string[]
|
||||
extraNodePaths: string[]
|
||||
},
|
||||
@@ -241,7 +241,7 @@ async function _rebuild (
|
||||
getSubgraphToBuild(
|
||||
lockfileWalker(
|
||||
ctx.currentLockfile,
|
||||
ctx.projects.map(({ id }) => id),
|
||||
Object.values(ctx.projects).map(({ id }) => id),
|
||||
{
|
||||
include: {
|
||||
dependencies: opts.production,
|
||||
@@ -324,7 +324,7 @@ async function _rebuild (
|
||||
return linkBins(modules, binPath, { warn })
|
||||
}))
|
||||
)
|
||||
await Promise.all(ctx.projects.map(async ({ rootDir }) => limitLinking(async () => {
|
||||
await Promise.all(Object.values(ctx.projects).map(async ({ rootDir }) => limitLinking(async () => {
|
||||
const modules = path.join(rootDir, 'node_modules')
|
||||
const binPath = path.join(modules, '.bin')
|
||||
return linkBins(modules, binPath, {
|
||||
|
||||
@@ -121,6 +121,7 @@ export async function handler (
|
||||
await rebuildSelectedPkgs(
|
||||
[
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: await readProjectManifestOnly(rebuildOpts.dir, opts),
|
||||
rootDir: rebuildOpts.dir,
|
||||
},
|
||||
|
||||
@@ -203,6 +203,7 @@ export default async function run (inputArgv: string[]) {
|
||||
process.exitCode = 0
|
||||
return
|
||||
}
|
||||
config.allProjectsGraph = filterResults.allProjectsGraph
|
||||
config.selectedProjectsGraph = filterResults.selectedProjectsGraph
|
||||
if (isEmpty(config.selectedProjectsGraph)) {
|
||||
if (printLogs) {
|
||||
|
||||
Reference in New Issue
Block a user