-
-
Notifications
You must be signed in to change notification settings - Fork 936
/
index.ts
112 lines (102 loc) · 3.72 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { promises as fs, Stats } from 'fs'
import path from 'path'
import type { DirectoryFetcher, DirectoryFetcherOptions } from '@pnpm/fetcher-base'
import { logger } from '@pnpm/logger'
import { safeReadProjectManifestOnly } from '@pnpm/read-project-manifest'
import fromPairs from 'ramda/src/fromPairs'
import packlist from 'npm-packlist'
const directoryFetcherLogger = logger('directory-fetcher')
export interface CreateDirectoryFetcherOptions {
includeOnlyPackageFiles?: boolean
}
export function createDirectoryFetcher (
opts?: CreateDirectoryFetcherOptions
) {
const fetchFromDir = opts?.includeOnlyPackageFiles ? fetchPackageFilesFromDir : fetchAllFilesFromDir
const directoryFetcher: DirectoryFetcher = (cafs, resolution, opts) => {
const dir = path.join(opts.lockfileDir, resolution.directory)
return fetchFromDir(dir, opts)
}
return {
directory: directoryFetcher,
}
}
type FetchFromDirOpts = Omit<DirectoryFetcherOptions, 'lockfileDir'>
export async function fetchFromDir (
dir: string,
opts: FetchFromDirOpts & CreateDirectoryFetcherOptions
) {
if (opts.includeOnlyPackageFiles) {
return fetchPackageFilesFromDir(dir, opts)
}
return fetchAllFilesFromDir(dir, opts)
}
async function fetchAllFilesFromDir (
dir: string,
opts: FetchFromDirOpts
) {
const filesIndex = await _fetchAllFilesFromDir(dir)
if (opts.manifest) {
// In a regular pnpm workspace it will probably never happen that a dependency has no package.json file.
// Safe read was added to support the Bit workspace in which the components have no package.json files.
// Related PR in Bit: https://github.com/teambit/bit/pull/5251
const manifest = await safeReadProjectManifestOnly(dir) ?? {}
opts.manifest.resolve(manifest as any) // eslint-disable-line @typescript-eslint/no-explicit-any
}
return {
local: true as const,
filesIndex,
packageImportMethod: 'hardlink' as const,
}
}
async function _fetchAllFilesFromDir (
dir: string,
relativeDir = ''
): Promise<Record<string, string>> {
const filesIndex: Record<string, string> = {}
const files = await fs.readdir(dir)
await Promise.all(files
.filter((file) => file !== 'node_modules')
.map(async (file) => {
const filePath = path.join(dir, file)
let stat: Stats
try {
stat = await fs.stat(filePath)
} catch (err: any) { // eslint-disable-line @typescript-eslint/no-explicit-any
// Broken symlinks are skipped
if (err.code === 'ENOENT') {
directoryFetcherLogger.debug({ brokenSymlink: filePath })
return
}
throw err
}
const relativeSubdir = `${relativeDir}${relativeDir ? '/' : ''}${file}`
if (stat.isDirectory()) {
const subFilesIndex = await _fetchAllFilesFromDir(filePath, relativeSubdir)
Object.assign(filesIndex, subFilesIndex)
} else {
filesIndex[relativeSubdir] = filePath
}
})
)
return filesIndex
}
async function fetchPackageFilesFromDir (
dir: string,
opts: FetchFromDirOpts
) {
const files = await packlist({ path: dir })
const filesIndex: Record<string, string> = fromPairs(files.map((file) => [file, path.join(dir, file)]))
if (opts.manifest) {
// In a regular pnpm workspace it will probably never happen that a dependency has no package.json file.
// Safe read was added to support the Bit workspace in which the components have no package.json files.
// Related PR in Bit: https://github.com/teambit/bit/pull/5251
const manifest = await safeReadProjectManifestOnly(dir) ?? {}
opts.manifest.resolve(manifest as any) // eslint-disable-line @typescript-eslint/no-explicit-any
}
return {
local: true as const,
filesIndex,
packageImportMethod: 'hardlink' as const,
}
}