2024-11-02 22:39:03 +01:00
|
|
|
import { getNodeModulesBinDirPath } from "./nodeModulesBinDirPath";
|
2024-11-18 04:46:06 +01:00
|
|
|
import { join as pathJoin, resolve as pathResolve } from "path";
|
2024-11-02 22:39:03 +01:00
|
|
|
import * as fsPr from "fs/promises";
|
|
|
|
import { id } from "tsafe/id";
|
|
|
|
import { assert } from "tsafe/assert";
|
|
|
|
import chalk from "chalk";
|
2024-11-17 19:22:34 +01:00
|
|
|
import * as crypto from "crypto";
|
2024-11-18 04:46:06 +01:00
|
|
|
import { is } from "tsafe/is";
|
|
|
|
import { symToStr } from "tsafe/symToStr";
|
|
|
|
import { readThisNpmPackageVersion } from "./readThisNpmPackageVersion";
|
2024-11-02 22:39:03 +01:00
|
|
|
|
|
|
|
getIsPrettierAvailable.cache = id<boolean | undefined>(undefined);
|
|
|
|
|
|
|
|
export async function getIsPrettierAvailable(): Promise<boolean> {
|
|
|
|
if (getIsPrettierAvailable.cache !== undefined) {
|
|
|
|
return getIsPrettierAvailable.cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nodeModulesBinDirPath = getNodeModulesBinDirPath();
|
|
|
|
|
|
|
|
const prettierBinPath = pathJoin(nodeModulesBinDirPath, "prettier");
|
|
|
|
|
|
|
|
const stats = await fsPr.stat(prettierBinPath).catch(() => undefined);
|
|
|
|
|
|
|
|
const isPrettierAvailable = stats?.isFile() ?? false;
|
|
|
|
|
|
|
|
getIsPrettierAvailable.cache = isPrettierAvailable;
|
|
|
|
|
|
|
|
return isPrettierAvailable;
|
|
|
|
}
|
|
|
|
|
2024-11-17 19:22:34 +01:00
|
|
|
type PrettierAndConfigHash = {
|
2024-11-02 22:39:03 +01:00
|
|
|
prettier: typeof import("prettier");
|
2024-11-17 19:22:34 +01:00
|
|
|
configHash: string;
|
2024-11-02 22:39:03 +01:00
|
|
|
};
|
|
|
|
|
2024-11-17 19:22:34 +01:00
|
|
|
getPrettier.cache = id<PrettierAndConfigHash | undefined>(undefined);
|
2024-11-02 22:39:03 +01:00
|
|
|
|
2024-11-17 19:22:34 +01:00
|
|
|
export async function getPrettier(): Promise<PrettierAndConfigHash> {
|
2024-11-02 22:39:03 +01:00
|
|
|
assert(getIsPrettierAvailable());
|
|
|
|
|
2024-11-17 19:22:34 +01:00
|
|
|
if (getPrettier.cache !== undefined) {
|
|
|
|
return getPrettier.cache;
|
2024-11-02 22:39:03 +01:00
|
|
|
}
|
|
|
|
|
2024-11-18 04:46:06 +01:00
|
|
|
let prettier = id<typeof import("prettier") | undefined>(undefined);
|
|
|
|
|
|
|
|
import_prettier: {
|
|
|
|
// NOTE: When module is linked we want to make sure we import the correct version
|
|
|
|
// of prettier, that is the one of the project, not the one of this repo.
|
|
|
|
// So we do a sketchy eval to bypass ncc.
|
|
|
|
// We make sure to only do that when linking, otherwise we import properly.
|
|
|
|
if (readThisNpmPackageVersion() === "0.0.0") {
|
|
|
|
eval(
|
|
|
|
`${symToStr({ prettier })} = require("${pathResolve(pathJoin(getNodeModulesBinDirPath(), "..", "prettier"))}")`
|
|
|
|
);
|
|
|
|
|
|
|
|
assert(!is<undefined>(prettier));
|
|
|
|
|
|
|
|
break import_prettier;
|
|
|
|
}
|
|
|
|
|
|
|
|
prettier = await import("prettier");
|
|
|
|
}
|
2024-11-02 22:39:03 +01:00
|
|
|
|
2024-11-17 19:22:34 +01:00
|
|
|
const configHash = await (async () => {
|
|
|
|
const configFilePath = await prettier.resolveConfigFile(
|
|
|
|
pathJoin(getNodeModulesBinDirPath(), "..")
|
|
|
|
);
|
|
|
|
|
|
|
|
if (configFilePath === null) {
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
const data = await fsPr.readFile(configFilePath);
|
|
|
|
|
|
|
|
return crypto.createHash("sha256").update(data).digest("hex");
|
|
|
|
})();
|
|
|
|
|
|
|
|
const prettierAndConfig: PrettierAndConfigHash = {
|
2024-11-02 22:39:03 +01:00
|
|
|
prettier,
|
2024-11-17 19:22:34 +01:00
|
|
|
configHash
|
2024-11-02 22:39:03 +01:00
|
|
|
};
|
|
|
|
|
2024-11-17 19:22:34 +01:00
|
|
|
getPrettier.cache = prettierAndConfig;
|
2024-11-02 22:39:03 +01:00
|
|
|
|
|
|
|
return prettierAndConfig;
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function runPrettier(params: {
|
|
|
|
sourceCode: string;
|
|
|
|
filePath: string;
|
|
|
|
}): Promise<string> {
|
|
|
|
const { sourceCode, filePath } = params;
|
|
|
|
|
|
|
|
let formattedSourceCode: string;
|
|
|
|
|
|
|
|
try {
|
2024-11-17 19:22:34 +01:00
|
|
|
const { prettier } = await getPrettier();
|
2024-11-02 22:39:03 +01:00
|
|
|
|
2024-11-16 21:37:14 +01:00
|
|
|
const { ignored, inferredParser } = await prettier.getFileInfo(filePath, {
|
|
|
|
resolveConfig: true
|
|
|
|
});
|
|
|
|
|
|
|
|
if (ignored) {
|
|
|
|
return sourceCode;
|
|
|
|
}
|
|
|
|
|
2024-11-17 19:22:34 +01:00
|
|
|
const config = await prettier.resolveConfig(filePath);
|
|
|
|
|
2024-11-16 21:37:14 +01:00
|
|
|
formattedSourceCode = await prettier.format(sourceCode, {
|
|
|
|
...config,
|
|
|
|
filePath,
|
|
|
|
parser: inferredParser ?? undefined
|
|
|
|
});
|
2024-11-02 22:39:03 +01:00
|
|
|
} catch (error) {
|
|
|
|
console.log(
|
|
|
|
chalk.red(
|
|
|
|
`You probably need to upgrade the version of prettier in your project`
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return formattedSourceCode;
|
|
|
|
}
|