Skip to content

Commit e051c7f

Browse files
authored
Merge pull request #177 from goestav/feature/support-multiple-package-managers
Feature: support multiple package managers
2 parents 3729bc2 + b8d7fa0 commit e051c7f

File tree

5 files changed

+2726
-2159
lines changed

5 files changed

+2726
-2159
lines changed

.changeset/real-points-carry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@arethetypeswrong/cli": minor
3+
---
4+
5+
Add support for multiple package managers like [pnpm](https://pnpm.io/) and [yarn](https://yarnpkg.com/) ([#173](https://github.com/arethetypeswrong/arethetypeswrong.github.io/issues/173))

packages/cli/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"@types/marked-terminal": "^3.1.3",
5050
"@types/node": "^20.2.5",
5151
"@types/semver": "^7.5.3",
52+
"@types/which-pm-runs": "^1.0.2",
5253
"ts-expose-internals-conditionally": "1.0.0-empty.0",
5354
"typescript": "5.3.3"
5455
},
@@ -59,7 +60,8 @@
5960
"commander": "^10.0.1",
6061
"marked": "^9.1.2",
6162
"marked-terminal": "^6.0.0",
62-
"semver": "^7.5.4"
63+
"semver": "^7.5.4",
64+
"which-pm-runs": "^1.1.0"
6365
},
6466
"engines": {
6567
"node": ">=18"

packages/cli/src/index.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import { readConfig } from "./readConfig.js";
1515
import * as render from "./render/index.js";
1616
import { major, minor } from "semver";
1717
import { getExitCode } from "./getExitCode.js";
18+
import { determinePackCommand, determineTarballFilename } from "./utils.js";
19+
import detectPackageManager from "which-pm-runs";
1820

1921
const packageJson = createRequire(import.meta.url)("../package.json");
2022
const version = packageJson.version;
@@ -74,8 +76,8 @@ particularly ESM-related module resolution issues.`,
7476
.option("--exclude-entrypoints <entrypoints...>", "Specify entrypoints to exclude from checking.")
7577
.option(
7678
"--entrypoints-legacy",
77-
'In packages without the `exports` field, every file is an entry point. Specifying this option ' +
78-
'only takes effect when no entrypoints are automatically detected, or explicitly provided with other options.'
79+
"In packages without the `exports` field, every file is an entry point. Specifying this option " +
80+
"only takes effect when no entrypoints are automatically detected, or explicitly provided with other options.",
7981
)
8082
.addOption(
8183
new Option("--ignore-rules <rules...>", "Specify rules to ignore").choices(Object.values(problemFlags)).default([]),
@@ -159,29 +161,30 @@ particularly ESM-related module resolution issues.`,
159161
);
160162
}
161163

164+
const packageManager = (await detectPackageManager()?.name) ?? "npm";
165+
const packCommand = determinePackCommand(packageManager);
166+
162167
if (!opts.pack) {
163168
if (!process.stdout.isTTY) {
164169
program.error(
165-
"Specifying a directory requires the --pack option to confirm that running `npm pack` is ok.",
170+
`Specifying a directory requires the --pack option to confirm that running \`${packCommand}\` is ok.`,
166171
);
167172
}
168173
const rl = readline.createInterface(process.stdin, process.stdout);
169174
const answer = await new Promise<string>((resolve) => {
170-
rl.question(`Run \`npm pack\`? (Pass -P/--pack to skip) (Y/n) `, resolve);
175+
rl.question(`Run \`${packCommand}\`? (Pass -P/--pack to skip) (Y/n) `, resolve);
171176
});
172177
rl.close();
173178
if (answer.trim() && !answer.trim().toLowerCase().startsWith("y")) {
174179
process.exit(1);
175180
}
176181
}
177182

178-
const manifest = JSON.parse(await readFile(path.join(fileOrDirectory, "package.json"), { encoding: "utf8" }));
179-
fileName = deleteTgz = path.join(
180-
fileOrDirectory,
181-
// https://github.com/npm/cli/blob/f875caa86900122819311dd77cde01c700fd1817/lib/utils/tar.js#L123-L125
182-
`${manifest.name.replace("@", "").replace("/", "-")}-${manifest.version}.tgz`,
183-
);
184-
execSync("npm pack", { cwd: fileOrDirectory, encoding: "utf8", stdio: "ignore" });
183+
fileName = deleteTgz = await determineTarballFilename(fileOrDirectory);
184+
185+
const packCommandWithFilename = determinePackCommand(packageManager, fileName);
186+
187+
execSync(packCommandWithFilename, { cwd: fileOrDirectory, encoding: "utf8", stdio: "ignore" });
185188
}
186189
const file = await readFile(fileName);
187190
const data = new Uint8Array(file);

packages/cli/src/utils.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { readFile } from "fs/promises";
2+
import path from "path";
3+
4+
/** Determine which CLI command to use to create a tarball from a package. */
5+
export const determinePackCommand = (packageManager: string, filename?: string) => {
6+
switch (packageManager) {
7+
case "pnpm":
8+
// PNPM does not support custom destination filenames (see: https://github.com/pnpm/pnpm/issues/7834)
9+
return "pnpm pack";
10+
case "yarn":
11+
return filename ? `yarn pack --out ${filename}` : "yarn pack";
12+
default:
13+
return filename ? `npm pack ${filename}` : "npm pack";
14+
}
15+
};
16+
17+
/** Determine which tarball filename to use. */
18+
export const determineTarballFilename = async (fileOrDirectory: string) => {
19+
const manifest = JSON.parse(await readFile(path.join(fileOrDirectory, "package.json"), { encoding: "utf8" }));
20+
21+
return path.join(
22+
fileOrDirectory,
23+
// https://github.com/npm/cli/blob/f875caa86900122819311dd77cde01c700fd1817/lib/utils/tar.js#L123-L125
24+
`${manifest.name.replace("@", "").replace("/", "-")}-${manifest.version}.tgz`,
25+
);
26+
};

0 commit comments

Comments
 (0)