Files
test-repo/tests/config/install-prettier.js
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

138 lines
4.2 KiB
JavaScript
Raw Normal View History

2025-02-25 08:07:03 +08:00
import { spawnSync } from "node:child_process";
2024-12-16 11:19:18 +08:00
import crypto from "node:crypto";
2021-11-29 10:07:11 +08:00
import fs from "node:fs";
2024-12-16 11:19:18 +08:00
import os from "node:os";
import path from "node:path";
2025-05-06 10:34:05 +08:00
import { performance } from "node:perf_hooks";
import { outdent } from "outdent";
2025-03-10 11:48:01 +08:00
import picocolors from "picocolors";
2024-12-16 11:19:18 +08:00
const isWindows = process.platform === "win32";
// https://github.com/sindresorhus/nano-spawn/blob/7f3fbe6590eec44f7e90f7735d173258dd80b420/source/windows.js#L71
const escapeFile = isWindows
? (file) => file.replace(/([()\][%!^"`<>&|;, *?])/g, "^$1")
: (file) => file;
// https://github.com/sindresorhus/nano-spawn/blob/7f3fbe6590eec44f7e90f7735d173258dd80b420/source/windows.js#L66
const escapeArgument = isWindows
? (argument) =>
escapeFile(
escapeFile(
`"${argument
.replace(/(\\*)"/g, String.raw`$1$1\"`)
.replace(/(\\*)$/, "$1$1")}"`,
),
)
: (argument) => argument;
const spawn = (command, args, options) =>
spawnSync(
[
escapeFile(command),
...args.map((argument) => escapeArgument(argument)),
].join(" "),
{
...options,
shell: true,
},
);
2024-12-16 11:19:18 +08:00
const createTemporaryDirectory = () => {
const directory = path.join(
2025-02-25 08:07:03 +08:00
// The following quoted from https://github.com/es-tooling/module-replacements/blob/27d1acd38f19741e31d2eae561a5c8a914373fc5/docs/modules/tempy.md?plain=1#L20-L21, not sure if it's true
// MacOS and possibly some other platforms return a symlink from `os.tmpdir`.
// For some applications, this can cause problems; thus, we use `realpath`.
fs.realpathSync(os.tmpdir()),
2024-12-16 11:19:18 +08:00
crypto.randomBytes(16).toString("hex"),
);
fs.mkdirSync(directory);
return directory;
};
2021-09-09 18:53:31 +08:00
const allowedClients = new Set(["yarn", "npm", "pnpm"]);
2025-05-06 10:34:05 +08:00
let client = process.env.PRETTIER_INSTALL_NPM_CLIENT;
2021-09-09 18:53:31 +08:00
if (!allowedClients.has(client)) {
client = "yarn";
}
const directoriesToClean = new Set();
2025-04-21 18:58:44 +08:00
process.once("exit", cleanUp);
function cleanUp() {
if (directoriesToClean.size === 0) {
return;
}
2025-03-10 11:48:01 +08:00
console.log(picocolors.green("Removing installed Prettier:"));
for (const directory of directoriesToClean) {
// Node.js<14 don't support `fs.rmSync`
try {
fs.rmSync(directory, { force: true, recursive: true });
} catch {
// No op
}
if (fs.existsSync(directory)) {
2025-03-10 11:48:01 +08:00
console.error(picocolors.red(` - ${picocolors.inverse(directory)} FAIL`));
} else {
2025-03-10 11:48:01 +08:00
console.log(picocolors.green(` - ${picocolors.inverse(directory)} DONE`));
}
}
}
2022-10-18 10:01:09 +08:00
function installPrettier(packageDirectory) {
2025-05-06 10:34:05 +08:00
const start = performance.now();
2022-10-18 10:01:09 +08:00
const temporaryDirectory = createTemporaryDirectory();
directoriesToClean.add(temporaryDirectory);
const fileName = spawn("npm", ["pack"], {
2022-10-18 10:01:09 +08:00
cwd: packageDirectory,
2025-02-25 08:07:03 +08:00
encoding: "utf8",
2021-11-29 10:07:11 +08:00
}).stdout.trim();
2022-10-18 10:01:09 +08:00
const file = path.join(packageDirectory, fileName);
const packed = path.join(temporaryDirectory, fileName);
2021-09-09 18:53:31 +08:00
fs.copyFileSync(file, packed);
fs.unlinkSync(file);
2022-10-18 10:01:09 +08:00
const runNpmClient = (args) =>
spawn(client, args, { cwd: temporaryDirectory });
2022-05-06 20:27:33 +08:00
runNpmClient(client === "pnpm" ? ["init"] : ["init", "-y"]);
2021-09-09 18:53:31 +08:00
switch (client) {
case "npm":
// npm fails when engine requirement only with `--engine-strict`
2022-05-06 20:27:33 +08:00
runNpmClient(["install", packed, "--engine-strict"]);
2021-09-09 18:53:31 +08:00
break;
case "pnpm":
// Note: current pnpm can't work with `--engine-strict` and engineStrict setting in `.npmrc`
2022-05-06 20:27:33 +08:00
runNpmClient(["add", packed, "--engine-strict"]);
2021-09-09 18:53:31 +08:00
break;
2022-05-06 20:27:33 +08:00
case "yarn":
2021-09-09 18:53:31 +08:00
// yarn fails when engine requirement not compatible by default
2022-05-06 20:27:33 +08:00
runNpmClient(["config", "set", "nodeLinker", "node-modules"]);
runNpmClient(["add", `prettier@file:${packed}`]);
// No default
2021-09-09 18:53:31 +08:00
}
fs.unlinkSync(packed);
console.log(
2025-03-10 11:48:01 +08:00
picocolors.green(
outdent`
Prettier installed
2025-05-06 10:34:05 +08:00
at ${picocolors.inverse(temporaryDirectory)}
2025-03-10 11:48:01 +08:00
from ${picocolors.inverse(packageDirectory)}
2025-05-06 10:34:05 +08:00
with ${picocolors.inverse(client)}
in ${picocolors.inverse(`${performance.now() - start}ms`)}.
`,
),
);
2022-10-18 10:01:09 +08:00
fs.writeFileSync(
path.join(temporaryDirectory, "index-proxy.mjs"),
"export * from 'prettier';",
);
return temporaryDirectory;
2021-11-29 10:07:11 +08:00
}
export default installPrettier;