|
1 | | -import { exists, log, spawn } from "builder-util" |
2 | | -import { CancellationToken } from "builder-util-runtime" |
3 | | -import * as fs from "fs-extra" |
4 | | -import * as path from "path" |
| 1 | +import { CancellationToken, Nullish } from "builder-util-runtime" |
5 | 2 | import { TmpDir } from "temp-file" |
6 | 3 | import { NpmNodeModulesCollector } from "./npmNodeModulesCollector" |
7 | | -import { detectYarnBerry as detectIfYarnBerry, detectPackageManagerByEnv, detectPackageManagerByFile, getPackageManagerCommand, PM } from "./packageManager" |
| 4 | +import { detectPackageManager, getPackageManagerCommand, PM } from "./packageManager" |
8 | 5 | import { PnpmNodeModulesCollector } from "./pnpmNodeModulesCollector" |
9 | 6 | import { NodeModuleInfo } from "./types" |
10 | 7 | import { YarnBerryNodeModulesCollector } from "./yarnBerryNodeModulesCollector" |
11 | 8 | import { YarnNodeModulesCollector } from "./yarnNodeModulesCollector" |
12 | 9 | import { BunNodeModulesCollector } from "./bunNodeModulesCollector" |
| 10 | +import { Lazy } from "lazy-val" |
| 11 | +import { spawn, log } from "builder-util" |
| 12 | +import * as fs from "fs-extra" |
| 13 | +import * as path from "path" |
13 | 14 |
|
14 | 15 | export { getPackageManagerCommand, PM } |
15 | 16 |
|
@@ -47,40 +48,26 @@ export function getNodeModules( |
47 | 48 | return collector.getNodeModules({ cancellationToken, packageName }) |
48 | 49 | } |
49 | 50 |
|
50 | | -export async function detectPackageManager(searchPaths: string[]): Promise<{ pm: PM; corepackConfig: string | undefined; resolvedDirectory: string | undefined }> { |
51 | | - let pm: PM | null = null |
52 | | - const dedupedPaths = Array.from(new Set(searchPaths)) // reduce file operations, dedupe paths since primary use case has projectDir === appDir |
53 | | - |
54 | | - const resolveIfYarn = (pm: PM, version: string, cwd: string) => (pm === PM.YARN ? detectIfYarnBerry(cwd, version) : pm) |
55 | | - |
56 | | - for (const dir of dedupedPaths) { |
57 | | - const packageJsonPath = path.join(dir, "package.json") |
58 | | - const packageManager = (await exists(packageJsonPath)) ? (await fs.readJson(packageJsonPath, "utf8"))?.packageManager : undefined |
59 | | - if (packageManager) { |
60 | | - const [pm, version] = packageManager.split("@") |
61 | | - if (Object.values(PM).includes(pm as PM)) { |
62 | | - const resolvedPackageManager = await resolveIfYarn(pm as PM, version, dir) |
63 | | - log.debug({ resolvedPackageManager, packageManager, cwd: dir }, "packageManager field detected in package.json") |
64 | | - return { pm: resolvedPackageManager, corepackConfig: packageManager, resolvedDirectory: dir } |
| 51 | +export const determinePackageManagerEnv = ({ projectDir, appDir, workspaceRoot }: { projectDir: string; appDir: string; workspaceRoot: string | Nullish }) => |
| 52 | + new Lazy(async () => { |
| 53 | + const availableDirs = [projectDir, appDir, workspaceRoot].filter((it): it is string => it != null) |
| 54 | + const pm = await detectPackageManager(availableDirs) |
| 55 | + const root = await findWorkspaceRoot(pm.pm, projectDir) |
| 56 | + if (root != null) { |
| 57 | + // re-detect package manager from workspace root, this seems particularly necessary for pnpm workspaces |
| 58 | + const actualPm = await detectPackageManager([root]) |
| 59 | + return { |
| 60 | + pm: actualPm.pm, |
| 61 | + workspaceRoot: Promise.resolve(actualPm.resolvedDirectory), |
65 | 62 | } |
66 | 63 | } |
67 | | - |
68 | | - pm = await detectPackageManagerByFile(dir) |
69 | | - if (pm) { |
70 | | - const resolvedPackageManager = await resolveIfYarn(pm, "", dir) |
71 | | - log.debug({ resolvedPackageManager, cwd: dir }, "packageManager detected by file") |
72 | | - return { pm: resolvedPackageManager, resolvedDirectory: dir, corepackConfig: undefined } |
| 64 | + return { |
| 65 | + pm: pm.pm, |
| 66 | + workspaceRoot: Promise.resolve(pm.resolvedDirectory), |
73 | 67 | } |
74 | | - } |
75 | | - |
76 | | - pm = detectPackageManagerByEnv() || PM.NPM |
77 | | - const cwd = process.env.npm_package_json ? path.dirname(process.env.npm_package_json) : (process.env.INIT_CWD ?? process.cwd()) |
78 | | - const resolvedPackageManager = await resolveIfYarn(pm, "", cwd) |
79 | | - log.debug({ resolvedPackageManager, detected: cwd }, "packageManager not detected by file, falling back to environment detection") |
80 | | - return { pm: resolvedPackageManager, resolvedDirectory: undefined, corepackConfig: undefined } |
81 | | -} |
| 68 | + }) |
82 | 69 |
|
83 | | -export async function findWorkspaceRoot(pm: PM, cwd: string): Promise<string | undefined> { |
| 70 | +async function findWorkspaceRoot(pm: PM, cwd: string): Promise<string | undefined> { |
84 | 71 | let command: { command: string; args: string[] } | undefined |
85 | 72 |
|
86 | 73 | switch (pm) { |
|
0 commit comments