@visulima/package
Version:
One Package to rule them all, finds your root-dir, monorepo, or package manager.
171 lines (166 loc) • 6.07 kB
JavaScript
import { execSync } from 'node:child_process';
import { existsSync, readFileSync } from 'node:fs';
import { findUp, findUpSync } from '@visulima/fs';
import { NotFoundError } from '@visulima/fs/error';
import { join, dirname } from '@visulima/path';
import { parsePackageJson } from './package-json.mjs';
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
const lockFileNames = ["yarn.lock", "package-lock.json", "pnpm-lock.yaml", "npm-shrinkwrap.json", "bun.lockb"];
const packageMangerFindUpMatcher = /* @__PURE__ */ __name((directory) => {
let lockFile;
lockFileNames.forEach((lockFileName) => {
if (!lockFile && existsSync(join(directory, lockFileName))) {
lockFile = join(directory, lockFileName);
}
});
if (lockFile) {
return lockFile;
}
const packageJsonFilePath = join(directory, "package.json");
if (existsSync(packageJsonFilePath)) {
const packageJson = parsePackageJson(readFileSync(packageJsonFilePath, "utf8"));
if (packageJson.packageManager !== void 0) {
return packageJsonFilePath;
}
}
return void 0;
}, "packageMangerFindUpMatcher");
const findPackageManagerOnFile = /* @__PURE__ */ __name((foundFile) => {
if (!foundFile) {
throw new NotFoundError("Could not find a package manager");
}
if (foundFile.endsWith("package.json")) {
const packageJson = parsePackageJson(foundFile);
if (packageJson.packageManager) {
const packageManagerNames = ["npm", "yarn", "pnpm", "bun"];
const foundPackageManager = packageManagerNames.find((prefix) => packageJson.packageManager.startsWith(prefix));
if (foundPackageManager) {
return {
packageManager: foundPackageManager,
path: dirname(foundFile)
};
}
}
}
if (foundFile.endsWith("yarn.lock")) {
return {
packageManager: "yarn",
path: dirname(foundFile)
};
}
if (foundFile.endsWith("package-lock.json") || foundFile.endsWith("npm-shrinkwrap.json")) {
return {
packageManager: "npm",
path: dirname(foundFile)
};
}
if (foundFile.endsWith("pnpm-lock.yaml")) {
return {
packageManager: "pnpm",
path: dirname(foundFile)
};
}
if (foundFile.endsWith("bun.lockb")) {
return {
packageManager: "bun",
path: dirname(foundFile)
};
}
throw new NotFoundError("Could not find a package manager");
}, "findPackageManagerOnFile");
const findLockFile = /* @__PURE__ */ __name(async (cwd) => {
const filePath = await findUp(lockFileNames, {
type: "file",
...cwd && { cwd }
});
if (!filePath) {
throw new Error("Could not find lock file");
}
return filePath;
}, "findLockFile");
const findLockFileSync = /* @__PURE__ */ __name((cwd) => {
const filePath = findUpSync(lockFileNames, {
type: "file",
...cwd && { cwd }
});
if (!filePath) {
throw new Error("Could not find lock file");
}
return filePath;
}, "findLockFileSync");
const findPackageManager = /* @__PURE__ */ __name(async (cwd) => {
const foundFile = await findUp(packageMangerFindUpMatcher, {
...cwd && { cwd }
});
return findPackageManagerOnFile(foundFile);
}, "findPackageManager");
const findPackageManagerSync = /* @__PURE__ */ __name((cwd) => {
const foundFile = findUpSync(packageMangerFindUpMatcher, {
...cwd && { cwd }
});
return findPackageManagerOnFile(foundFile);
}, "findPackageManagerSync");
const getPackageManagerVersion = /* @__PURE__ */ __name((name) => execSync(`${name} --version`).toString("utf8").trim(), "getPackageManagerVersion");
const identifyInitiatingPackageManager = /* @__PURE__ */ __name(async () => {
if (!process.env.npm_config_user_agent) {
return void 0;
}
const pmSpec = process.env.npm_config_user_agent.split(" ")[0];
const separatorPos = pmSpec.lastIndexOf("/");
const name = pmSpec.slice(0, Math.max(0, separatorPos));
return {
name: name === "npminstall" ? "cnpm" : name,
version: pmSpec.slice(Math.max(0, separatorPos + 1))
};
}, "identifyInitiatingPackageManager");
const generateMissingPackagesInstallMessage = /* @__PURE__ */ __name((packageName, missingPackages, options) => {
const s = missingPackages.length === 1 ? "" : "s";
if (options.packageManagers === void 0) {
options.packageManagers = ["npm", "pnpm", "yarn"];
}
if (options.packageManagers.length === 0) {
throw new Error("No package managers provided, please provide at least one package manager");
}
if (missingPackages.length === 0) {
throw new Error("No missing packages provided, please provide at least one missing package");
}
let message = `
${options.preMessage ?? ""}
${packageName} could not find the following package${s}
${missingPackages.join("\n ")}
To install the missing package${s}, please run the following command:
`;
const atLatest = /* @__PURE__ */ __name((name) => {
if (!name.split("@").includes("@")) {
return `${name}@latest`;
}
return name;
}, "atLatest");
const packageManagerCommands = options.packageManagers.map((packageManager) => {
const missingPackagesString = missingPackages.map((element) => atLatest(element)).join(" ");
switch (packageManager) {
case "bun": {
return ` bun add ${missingPackagesString} -D`;
}
case "npm": {
return ` npm install ${missingPackagesString} --save-dev`;
}
case "pnpm": {
return ` pnpm add ${missingPackagesString} -D`;
}
case "yarn": {
return ` yarn add ${missingPackagesString} --dev`;
}
default: {
throw new Error("Unknown package manager");
}
}
});
message += packageManagerCommands.join("\n\nor\n\n");
if (options.postMessage) {
message += options.postMessage;
}
return message;
}, "generateMissingPackagesInstallMessage");
export { findLockFile, findLockFileSync, findPackageManager, findPackageManagerSync, generateMissingPackagesInstallMessage, getPackageManagerVersion, identifyInitiatingPackageManager };