mirror of
https://github.com/pnpm/pnpm.git
synced 2026-05-13 19:16:21 -04:00
refactor: base on allProjects
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import path from 'path'
|
||||
import url from 'url'
|
||||
import pick from 'ramda/src/pick'
|
||||
import normalizePath from 'normalize-path'
|
||||
import {
|
||||
type DirectoryResolution,
|
||||
type LockfileObject,
|
||||
@@ -37,11 +38,10 @@ const INHERITED_MANIFEST_KEYS = [
|
||||
export type DeployManifest = Pick<ProjectManifest, typeof INHERITED_MANIFEST_KEYS[number] | DependenciesField>
|
||||
|
||||
export interface CreateDeployFilesOptions {
|
||||
allProjects: Array<Pick<Project, 'manifest' | 'rootDirRealPath'>>
|
||||
allProjects: Array<Pick<Project, 'manifest' | 'rootDir' | 'rootDirRealPath'>>
|
||||
lockfile: LockfileObject
|
||||
lockfileDir: string
|
||||
manifest: DeployManifest
|
||||
projectId: ProjectId
|
||||
selectedProject: Pick<Project, 'manifest' | 'rootDir'>
|
||||
}
|
||||
|
||||
export interface DeployFiles {
|
||||
@@ -53,11 +53,10 @@ export function createDeployFiles ({
|
||||
allProjects,
|
||||
lockfile,
|
||||
lockfileDir,
|
||||
manifest,
|
||||
projectId,
|
||||
selectedProject,
|
||||
}: CreateDeployFilesOptions): DeployFiles {
|
||||
const deployedProjectRealPath = path.resolve(lockfileDir, projectId) as ProjectRootDirRealPath
|
||||
const inputSnapshot = lockfile.importers[projectId]
|
||||
const selectedProjectId = normalizePath(path.relative(lockfileDir, selectedProject.rootDir)) as ProjectId
|
||||
const inputSnapshot = lockfile.importers[selectedProjectId]
|
||||
|
||||
const targetSnapshot: ProjectSnapshot = {
|
||||
...inputSnapshot,
|
||||
@@ -71,12 +70,12 @@ export function createDeployFiles ({
|
||||
...lockfile.packages,
|
||||
}
|
||||
|
||||
for (const importerPath in lockfile.importers) {
|
||||
if (importerPath === projectId) continue
|
||||
const projectSnapshot = lockfile.importers[importerPath as ProjectId]
|
||||
const importerRealPath = path.resolve(lockfileDir, importerPath) as ProjectRootDirRealPath
|
||||
const packageSnapshot = convertProjectSnapshotToPackageSnapshot(projectSnapshot, importerRealPath, allProjects, deployedProjectRealPath)
|
||||
const depPath = createFileUrlDepPath(importerRealPath, allProjects)
|
||||
for (const project of allProjects) {
|
||||
if (project.rootDir === selectedProject.rootDir) continue
|
||||
const projectId = (normalizePath(path.relative(lockfileDir, project.rootDir)) || '.') as ProjectId
|
||||
const projectSnapshot = lockfile.importers[projectId]
|
||||
const packageSnapshot = convertProjectSnapshotToPackageSnapshot(projectSnapshot, project, selectedProject)
|
||||
const depPath = createFileUrlDepPath(project)
|
||||
targetPackageSnapshots[depPath] = packageSnapshot
|
||||
}
|
||||
|
||||
@@ -93,8 +92,14 @@ export function createDeployFiles ({
|
||||
}
|
||||
|
||||
const { targetPath } = splitPrefixResult
|
||||
const targetRealPath = path.resolve(lockfileDir, projectId, targetPath) as ProjectRootDirRealPath // importer IDs are relative to its project dir
|
||||
targetSpecifiers[name] = targetDependencies[name] = createFileUrlDepPath(targetRealPath, allProjects)
|
||||
const depRealPath = path.resolve(selectedProject.rootDir, targetPath) as ProjectRootDirRealPath
|
||||
const depProject = allProjects.find(project => project.rootDirRealPath === depRealPath)
|
||||
if (depProject) {
|
||||
targetSpecifiers[name] = targetDependencies[name] = createFileUrlDepPath(depProject)
|
||||
} else {
|
||||
// if this branch is reached, it means that there is a bug in pnpm that needs to be fixed
|
||||
throw new Error(`Cannot find any project in opts.allProject whose rootDirRealPath is '${depRealPath}'`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +112,7 @@ export function createDeployFiles ({
|
||||
packages: targetPackageSnapshots,
|
||||
},
|
||||
manifest: {
|
||||
...pick(INHERITED_MANIFEST_KEYS, manifest),
|
||||
...pick(INHERITED_MANIFEST_KEYS, selectedProject.manifest),
|
||||
dependencies: targetSnapshot.dependencies,
|
||||
devDependencies: targetSnapshot.devDependencies,
|
||||
optionalDependencies: targetSnapshot.optionalDependencies,
|
||||
@@ -117,16 +122,15 @@ export function createDeployFiles ({
|
||||
|
||||
function convertProjectSnapshotToPackageSnapshot (
|
||||
projectSnapshot: ProjectSnapshot,
|
||||
importerRealPath: string,
|
||||
allProjects: CreateDeployFilesOptions['allProjects'],
|
||||
deployedProjectRealPath: ProjectRootDirRealPath
|
||||
inputProject: Pick<Project, 'manifest' | 'rootDir'>,
|
||||
selectedProject: Pick<Project, 'manifest' | 'rootDir'>
|
||||
): PackageSnapshot {
|
||||
const resolution: DirectoryResolution = {
|
||||
type: 'directory',
|
||||
directory: '.',
|
||||
}
|
||||
const dependencies = convertResolvedDependencies(projectSnapshot.dependencies, importerRealPath, allProjects, deployedProjectRealPath)
|
||||
const optionalDependencies = convertResolvedDependencies(projectSnapshot.optionalDependencies, importerRealPath, allProjects, deployedProjectRealPath)
|
||||
const dependencies = convertResolvedDependencies(projectSnapshot.dependencies, inputProject, selectedProject)
|
||||
const optionalDependencies = convertResolvedDependencies(projectSnapshot.optionalDependencies, inputProject, selectedProject)
|
||||
return {
|
||||
dependencies,
|
||||
optionalDependencies,
|
||||
@@ -136,9 +140,8 @@ function convertProjectSnapshotToPackageSnapshot (
|
||||
|
||||
function convertResolvedDependencies (
|
||||
input: ResolvedDependencies | undefined,
|
||||
importerRealPath: string,
|
||||
allProjects: CreateDeployFilesOptions['allProjects'],
|
||||
deployedProjectRealPath: ProjectRootDirRealPath
|
||||
inputProject: Pick<Project, 'manifest' | 'rootDir'>,
|
||||
selectedProject: Pick<Project, 'manifest' | 'rootDir'>
|
||||
): ResolvedDependencies | undefined {
|
||||
if (!input) return undefined
|
||||
const output: ResolvedDependencies = {}
|
||||
@@ -152,18 +155,18 @@ function convertResolvedDependencies (
|
||||
}
|
||||
|
||||
const { targetPath } = splitPrefixResult
|
||||
const depRealPath = path.resolve(importerRealPath, targetPath) as ProjectRootDirRealPath
|
||||
if (['', '.'].includes(path.relative(importerRealPath, depRealPath))) {
|
||||
const depRealPath = path.resolve(inputProject.rootDir, targetPath)
|
||||
if (['', '.'].includes(path.relative(inputProject.rootDir, depRealPath))) {
|
||||
output[key] = 'link:.'
|
||||
continue
|
||||
}
|
||||
|
||||
if (depRealPath === deployedProjectRealPath) {
|
||||
if (depRealPath === selectedProject.rootDir) {
|
||||
output[key] = '../../..' // which is the deployed project location relative to the dependency dir within the virtual dir
|
||||
continue
|
||||
}
|
||||
|
||||
output[key] = createFileUrlDepPath(depRealPath, allProjects)
|
||||
output[key] = createFileUrlDepPath(inputProject)
|
||||
}
|
||||
|
||||
return output
|
||||
@@ -181,12 +184,8 @@ function splitPrefix (spec: string): SplitPrefixResult | undefined {
|
||||
return { prefix, targetPath }
|
||||
}
|
||||
|
||||
function createFileUrlDepPath (
|
||||
depRealPath: ProjectRootDirRealPath,
|
||||
allProjects: CreateDeployFilesOptions['allProjects']
|
||||
): DepPath {
|
||||
const depFileUrl = url.pathToFileURL(depRealPath).toString()
|
||||
const project = allProjects.find(project => project.rootDirRealPath === depRealPath)
|
||||
const name = project?.manifest.name ?? path.basename(depRealPath)
|
||||
function createFileUrlDepPath (inputProject: Pick<Project, 'manifest' | 'rootDir'>): DepPath {
|
||||
const depFileUrl = url.pathToFileURL(inputProject.rootDir).toString()
|
||||
const name = inputProject.manifest.name ?? path.basename(inputProject.rootDir)
|
||||
return `${name}@${depFileUrl}` as DepPath
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@ import rimraf from '@zkochan/rimraf'
|
||||
import renderHelp from 'render-help'
|
||||
import { deployHook } from './deployHook'
|
||||
import { logger, globalWarn } from '@pnpm/logger'
|
||||
import { type Project, type ProjectId } from '@pnpm/types'
|
||||
import normalizePath from 'normalize-path'
|
||||
import { type Project } from '@pnpm/types'
|
||||
import { createDeployFiles } from './createDeployFiles'
|
||||
import { deployCatalogHook } from './deployCatalogHook'
|
||||
|
||||
@@ -155,7 +154,7 @@ async function deployFromSharedLockfile (
|
||||
},
|
||||
deployDir: string
|
||||
): Promise<string | undefined> {
|
||||
const { allProjects, lockfileDir, workspaceDir } = opts
|
||||
const { allProjects, lockfileDir } = opts
|
||||
|
||||
if (!allProjects) {
|
||||
return 'opts.allProjects is undefined. Falling back to installing without a lockfile.'
|
||||
@@ -165,23 +164,16 @@ async function deployFromSharedLockfile (
|
||||
return 'opts.lockfileDir is undefined. Falling back to installing without a lockfile.'
|
||||
}
|
||||
|
||||
if (!workspaceDir) {
|
||||
return 'opts.workspaceDir is undefined. Falling back to installing without a lockfile.'
|
||||
}
|
||||
|
||||
const lockfile = await readWantedLockfile(lockfileDir, { ignoreIncompatible: false })
|
||||
if (!lockfile) {
|
||||
return 'Shared lockfile not found. Falling back to installing without a lockfile.'
|
||||
}
|
||||
|
||||
const projectId = normalizePath(path.relative(workspaceDir, selectedProject.rootDir)) as ProjectId
|
||||
|
||||
const deployFiles = createDeployFiles({
|
||||
allProjects,
|
||||
lockfile,
|
||||
lockfileDir,
|
||||
manifest: selectedProject.manifest,
|
||||
projectId,
|
||||
selectedProject,
|
||||
})
|
||||
|
||||
await Promise.all([
|
||||
|
||||
@@ -199,7 +199,7 @@ test('deploy with a shared lockfile after full install', async () => {
|
||||
expect(fs.existsSync(`deploy/node_modules/.pnpm/${project2Name}/node_modules/project-2/index.js`)).toBeTruthy()
|
||||
expect(fs.existsSync(`deploy/node_modules/.pnpm/${project2Name}/node_modules/project-2/test.js`)).toBeFalsy()
|
||||
const project3Name = fs.readdirSync('deploy/node_modules/.pnpm').find(name => name.startsWith('project-3@'))
|
||||
expect(project3Name).toBeDefined()
|
||||
expect(project3Name).toBeUndefined()
|
||||
expect(globalWarn).not.toHaveBeenCalledWith(expect.stringContaining('Falling back to installing without a lockfile'))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user