|
1 | | -import fs from 'node:fs'; |
2 | | -import path from 'node:path'; |
| 1 | +import type { PackageManager, PackageManagerId } from '@tomjs/pkg'; |
| 2 | +import { getPackageManager } from '@tomjs/pkg'; |
3 | 3 | import chalk from 'chalk'; |
4 | 4 | import semver from 'semver'; |
5 | | -import type { PackageJson } from 'type-fest'; |
6 | | -import { joinArray, run } from './utils.js'; |
7 | 5 |
|
8 | | -export type PackageManagerCLI = 'npm' | 'pnpm' | 'yarn'; |
9 | | -export type PackageManagerId = 'npm' | 'pnpm' | 'yarn' | 'berry'; |
10 | | - |
11 | | -export interface PackageManager { |
12 | | - /** |
13 | | - * The main CLI, e.g. the `npm` in `npm install`, `npm test`, etc. |
14 | | - */ |
15 | | - cli: PackageManagerCLI; |
16 | | - /** |
17 | | - * How the package manager should be referred to in user-facing messages (since there are two different configs for some, e.g. yarn and berry). |
18 | | - */ |
19 | | - id: PackageManagerId; |
20 | | - /** |
21 | | - * The version of the package manager. |
22 | | - */ |
23 | | - version?: string; |
24 | | - /** |
25 | | - * The minimum version of the package manager required. |
26 | | - */ |
27 | | - minVersion?: string; |
28 | | - /** |
29 | | - * The package manager is not supported. |
30 | | - */ |
31 | | - isNotSupported?: boolean; |
32 | | - /** |
33 | | - * Whether the package manager supports workspace protocol (`workspace:`). |
34 | | - */ |
35 | | - workspaceProtocol?: boolean; |
36 | | - /** |
37 | | - * List of lockfile names expected for this package manager, relative to CWD. e.g. `['package-lock.json', 'npm-shrinkwrap.json']`. |
38 | | - */ |
39 | | - lockfiles: string[]; |
40 | | -} |
41 | | - |
42 | | -const configs: Record<PackageManagerId, PackageManager> = { |
43 | | - npm: { |
44 | | - cli: 'npm', |
45 | | - id: 'npm', |
46 | | - minVersion: '7.0.0', |
47 | | - lockfiles: ['package-lock.json', 'npm-shrinkwrap.json'], |
48 | | - }, |
49 | | - pnpm: { |
50 | | - cli: 'pnpm', |
51 | | - id: 'pnpm', |
52 | | - minVersion: '8.0.0', |
53 | | - lockfiles: ['pnpm-lock.yaml'], |
54 | | - }, |
55 | | - yarn: { |
56 | | - cli: 'yarn', |
57 | | - id: 'yarn', |
58 | | - lockfiles: ['yarn.lock'], |
59 | | - }, |
60 | | - berry: { |
61 | | - cli: 'yarn', |
62 | | - id: 'berry', |
63 | | - minVersion: '3.1.0', |
64 | | - lockfiles: ['yarn.lock'], |
65 | | - }, |
66 | | -}; |
67 | | - |
68 | | -function configFromPackageManagerField(pkg: PackageJson) { |
69 | | - if (typeof pkg.packageManager !== 'string') { |
70 | | - return undefined; |
71 | | - } |
72 | | - |
73 | | - const [cli, version] = pkg.packageManager.split('@') as [PackageManagerCLI, string]; |
74 | | - |
75 | | - if (cli === 'yarn' && version && semver.gte(version, '2.0.0')) { |
76 | | - return configs['berry']; |
77 | | - } |
78 | | - |
79 | | - const config = configs[cli]; |
80 | | - if (config) { |
81 | | - return config; |
82 | | - } |
83 | | - |
84 | | - throw new Error(`Invalid package manager: ${chalk.green(pkg.packageManager)}`); |
85 | | -} |
86 | | - |
87 | | -function findLockfile(rootDirectory: string, config: PackageManager) { |
88 | | - return config.lockfiles |
89 | | - .map(filename => path.resolve(rootDirectory || '.', filename)) |
90 | | - .find(filepath => fs.existsSync(filepath)); |
91 | | -} |
92 | | - |
93 | | -function configFromLockfile(rootDirectory: string) { |
94 | | - return [configs.npm, configs.pnpm, configs.yarn].find(config => |
95 | | - findLockfile(rootDirectory, config), |
96 | | - ); |
97 | | -} |
98 | | - |
99 | | -export async function getPackageManagerConfig(rootDirectory: string, pkg: PackageJson) { |
100 | | - const pm = configFromPackageManagerField(pkg) || configFromLockfile(rootDirectory) || configs.npm; |
101 | | - |
102 | | - if (pm.isNotSupported) { |
103 | | - const supports = Object.keys(configs) |
104 | | - .filter(s => !configs[s].isNotSupported) |
105 | | - .map(s => { |
106 | | - const pm: PackageManager = configs[s]; |
107 | | - return pm.minVersion ? `${pm.cli}>=${pm.minVersion}` : pm.cli; |
108 | | - }); |
109 | | - throw new Error( |
110 | | - `Package manager ${chalk.green(pkg.packageManager)} is not supported. Please use one of the following: ${joinArray(supports)}.`, |
111 | | - ); |
112 | | - } |
113 | | - |
114 | | - // check version |
115 | | - let version: string = ''; |
116 | | - |
117 | | - try { |
118 | | - version = await run([pm.cli, '--version']); |
119 | | - pm.version = version; |
120 | | - } catch { |
121 | | - throw new Error(`Package manager ${chalk.green(pm.id)} is not installed`); |
122 | | - } |
123 | | - |
124 | | - if (!version) { |
125 | | - throw new Error( |
126 | | - `Package manager ${chalk.green(pm.id)} has unknown version, please make sure ${chalk.green(pm.id)} has been installed`, |
127 | | - ); |
128 | | - } |
129 | | - if (pm.minVersion && semver.lt(version, pm.minVersion)) { |
| 6 | +export async function getPackageManagerConfig(rootDir: string) { |
| 7 | + const pm: PackageManager = await getPackageManager(rootDir); |
| 8 | + const versions: Record<PackageManagerId, string> = { |
| 9 | + npm: '7.0.0', |
| 10 | + pnpm: '8.0.0', |
| 11 | + yarn: '', |
| 12 | + berry: '3.1.0', |
| 13 | + }; |
| 14 | + const minVersion = versions[pm.id]; |
| 15 | + |
| 16 | + if (minVersion && semver.lt(pm.version, minVersion)) { |
130 | 17 | throw new Error( |
131 | | - `Package manager ${chalk.green(pm.id)} version ${chalk.yellow(version)} is not supported, please upgrade to ${chalk.green(pm.minVersion)} or later`, |
| 18 | + `Package manager ${chalk.green(pm.id)} version ${chalk.yellow(pm.version)} is not supported, please upgrade to ${chalk.green(minVersion)} or later`, |
132 | 19 | ); |
133 | 20 | } |
134 | 21 |
|
|
0 commit comments