refactor: base on allProjects

This commit is contained in:
khai96_
2024-12-16 14:19:20 +07:00
parent 180a8b2165
commit 000788127c
3 changed files with 38 additions and 47 deletions

View File

@@ -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
}

View File

@@ -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([

View File

@@ -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'))
}